Обновление существующей базы данных с помощью кода структуры Entity Framework Сначала в MVC

В моем приложении MVC я использовал Entity Framework 6 и создал базу данных с первым подходом кода. Через некоторое время я обновил один из классов сущностей, добавив новый столбец и удалив некоторые столбцы. Для отражения этих изменений в базе данных я выполнил следующие шаги:

  • Удалена папка миграции в проекте.
  • Удалена таблица __MigrationHistory в базе данных.
  • Затем запустите следующую команду в консоли диспетчера пакетов:
    Enable-Migrations -EnableAutomaticMigrations -Force

  • Добавьте в конфигурационный файл следующие строки:
    AutomaticMigrationsEnabled = true;
            AutomaticMigrationDataLossAllowed = true;

  • Run:
    Add-Migration Initial

  • И, наконец, запустите:
    Обновление-База данных -Необходимо

Однако я столкнулся с ошибкой "В базе данных уже есть объект с именем" xxx "".

Чтобы избавиться от этой проблемы, я комментирую код в методе Up в исходном файле, созданном после 5-го шага. Это предотвращает ошибку, но ничего не изменяется в базе данных (обновленные таблицы сущностей остаются прежними). Где ошибка? Заранее благодарим за помощь.

Вот метод Up, который я прокомментировал в файле migration.cs:

    public override void Up()
    {
        CreateTable(
            "dbo.City",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    Name = c.String(nullable: false),
                    RegionID = c.Int(nullable: false),
                })
            .PrimaryKey(t => t.ID)
            .ForeignKey("dbo.Region", t => t.RegionID)
            .Index(t => t.RegionID);

        CreateTable(
            "dbo.Multiplier",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    Status = c.Int(nullable: false),
                    Term = c.Int(nullable: false),
                    CityID = c.Int(nullable: false),
                    WhoIsOnline = c.String(nullable: false),
                    UserId = c.String(nullable: false),
                    InstituteName = c.String(nullable: false),
                    InstituteStatusID = c.Int(nullable: false),
                    InstituteAccreditationDate = c.DateTime(nullable: false),
                    Address = c.String(nullable: false),
                    Phone = c.String(nullable: false),
                    Fax = c.String(),
                    Email = c.String(nullable: false),
                    EurodeskEmail = c.String(nullable: false),
                    WebSite = c.String(),
                    ContactName = c.String(nullable: false),
                    ContactSurname = c.String(nullable: false),
                    ContactJobTitle = c.String(),
                    ContactAssignmentDate = c.DateTime(),
                    ContactWorkingStart = c.String(),
                    ContactWorkingkEnd = c.String(),
                    ContactPhone = c.String(),
                    ContactMobile = c.String(nullable: false),
                    ContactEmail = c.String(nullable: false),
                    ContactCityID = c.Int(nullable: false),
                    LegalRepresentativeName = c.String(nullable: false),
                    LegalRepresentativeSurname = c.String(nullable: false),
                })
            .PrimaryKey(t => t.ID)
            .ForeignKey("dbo.City", t => t.CityID)
            .ForeignKey("dbo.InstituteStatus", t => t.InstituteStatusID)
            .Index(t => t.CityID)
            .Index(t => t.InstituteStatusID);

        CreateTable(
            "dbo.InstituteStatus",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    Name = c.String(nullable: false),
                })
            .PrimaryKey(t => t.ID);

        CreateTable(
            "dbo.TrainingParticipant",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    TrainingID = c.Int(nullable: false),
                    ParticipantID = c.Int(nullable: false),
                    Multiplier_ID = c.Int(),
                })
            .PrimaryKey(t => t.ID)
            .ForeignKey("dbo.Participant", t => t.ParticipantID)
            .ForeignKey("dbo.Training", t => t.TrainingID)
            .ForeignKey("dbo.Multiplier", t => t.Multiplier_ID)
            .Index(t => t.TrainingID)
            .Index(t => t.ParticipantID)
            .Index(t => t.Multiplier_ID);

        CreateTable(
            "dbo.Participant",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    Name = c.String(nullable: false),
                    Surname = c.String(nullable: false),
                    MultiplierID = c.Int(nullable: false),
                })
            .PrimaryKey(t => t.ID)
            .ForeignKey("dbo.Multiplier", t => t.MultiplierID)
            .Index(t => t.MultiplierID);

        CreateTable(
            "dbo.Training",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    Name = c.String(nullable: false),
                    Date = c.DateTime(nullable: false),
                    CityID = c.Int(nullable: false),
                })
            .PrimaryKey(t => t.ID)
            .ForeignKey("dbo.City", t => t.CityID)
            .Index(t => t.CityID);

        CreateTable(
            "dbo.Region",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    Name = c.String(nullable: false),
                })
            .PrimaryKey(t => t.ID);

    }


И это метод Down в файле migration.cs:

    public override void Down()
    {
        DropForeignKey("dbo.City", "RegionID", "dbo.Region");
        DropForeignKey("dbo.TrainingParticipant", "Multiplier_ID", "dbo.Multiplier");
        DropForeignKey("dbo.TrainingParticipant", "TrainingID", "dbo.Training");
        DropForeignKey("dbo.Training", "CityID", "dbo.City");
        DropForeignKey("dbo.TrainingParticipant", "ParticipantID", "dbo.Participant");
        DropForeignKey("dbo.Participant", "MultiplierID", "dbo.Multiplier");
        DropForeignKey("dbo.Multiplier", "InstituteStatusID", "dbo.InstituteStatus");
        DropForeignKey("dbo.Multiplier", "CityID", "dbo.City");
        DropIndex("dbo.Training", new[] { "CityID" });
        DropIndex("dbo.Participant", new[] { "MultiplierID" });
        DropIndex("dbo.TrainingParticipant", new[] { "Multiplier_ID" });
        DropIndex("dbo.TrainingParticipant", new[] { "ParticipantID" });
        DropIndex("dbo.TrainingParticipant", new[] { "TrainingID" });
        DropIndex("dbo.Multiplier", new[] { "InstituteStatusID" });
        DropIndex("dbo.Multiplier", new[] { "CityID" });
        DropIndex("dbo.City", new[] { "RegionID" });
        DropTable("dbo.Region");
        DropTable("dbo.Training");
        DropTable("dbo.Participant");
        DropTable("dbo.TrainingParticipant");
        DropTable("dbo.InstituteStatus");
        DropTable("dbo.Multiplier");
        DropTable("dbo.City");
    }

Ответ 1

Почему вы делали шаги 1-4? Это, где вы поступили не так. Если у вас была ранее созданная база данных, и вы просто вносите изменения в схему, просто создайте миграцию и примените ее. Выполняя шаги 1-4, вы фактически уничтожаете знание Entity Framework этой базы данных и, по сути, заканчиваете первым кодом с существующей базой данных. В этот момент вам нужно либо вручную изменить вашу схему, либо позволить Entity Framework выпустить ее и начать с нее.

Что касается возврата к состоянию, в котором вы можете применить миграцию снова, вы оказались на правильном пути, создав миграцию и просто опустошив метод Up. Однако вам нужно сделать это против предыдущего состояния приложения, то есть того, которое соответствует базе данных в ее нынешнем виде. В противном случае Entity Framework собирается создавать таблицы создания, которые включают изменения вашего кода. Итак, следующие шаги:

  • Отмените свой код до того, как вы начнете изменять свои POCOs.
  • Сгенерировать перенос.
  • Удалить все в Up
  • Применить миграцию с помощью update-database
  • Повторно примените изменения, внесенные в ваши POCO.
  • Сгенерируйте другую миграцию (теперь вместо этого нужно просто добавлять/изменять инструкции столбца)
  • Применить миграцию.

После этого вы должны хорошо вернуться. Затем, в следующий раз, когда вы вносите изменения в код, просто выполните шаги 5 и 6.

Ответ 2

У меня была эта точная проблема. Кажется, стоит отметить, что в этой ситуации есть команды, чтобы помочь в этой ситуации, а именно флаги -IgnoreChanges и -Force.

Я обрезал из multi-dbContext в одно приложение dbContext. Как вы можете догадаться, таблицы уже существовали, но в единственном контексте ничего не было из таблиц, которые поддерживались во втором контексте.

На самом деле это довольно просто (хотя 2 дня поиска ответа бесполезно привели меня к чтению в командных строках EF Code First Migrations и диспетчер пакетов...) Вот как я справился с этим.

Вы можете удалить папку миграции и таблицу _Migrations в SQL... это приведет к необходимости использования следующих параметров: Enable-Migrations -Force

Но вы должны уметь отбираться отсюда без принятия решительных мер:

  1. Add-migration "Reset" -IgnoreChanges -Force (принудительно игнорирует изменения, которые могут существовать в вашей модели/классе - хорошо для начала работы с существующей базой данных)
  2. Обновление базы данных (просто запись линии миграции в качестве основы)
  3. Add-migration "AddMyMigrationsToThisDb" -Force (принудительно выполняет итерацию объектной модели в коде, чтобы получить изменения)
  4. Обновление базы данных

Теперь вы должны вернуться к работе только для использования Add-Migration и Update-Database без дополнительных флагов.