Обновление существующей базы данных с помощью кода структуры 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
Но вы должны уметь отбираться отсюда без принятия решительных мер:
- Add-migration "Reset" -IgnoreChanges -Force (принудительно игнорирует изменения, которые могут существовать в вашей модели/классе - хорошо для начала работы с существующей базой данных)
- Обновление базы данных (просто запись линии миграции в качестве основы)
- Add-migration "AddMyMigrationsToThisDb" -Force (принудительно выполняет итерацию объектной модели в коде, чтобы получить изменения)
- Обновление базы данных
Теперь вы должны вернуться к работе только для использования Add-Migration и Update-Database без дополнительных флагов.