在 MVC 中使用 Entity Framework Code First 更新现有数据库
Update existing database with Entity Framework Code First in MVC
在我的 MVC 应用程序中,我使用了 Entity Framework6 并使用代码优先方法创建了数据库。一段时间后,我通过添加新列并删除一些列来更新实体 类 之一。为了将这些更改反映到数据库中,我按照以下步骤操作:
- Deleted the migrations folder in the project.
- Deleted the __MigrationHistory table in the database.
Then run the following command in the Package Manager Console:
Enable-Migrations -EnableAutomaticMigrations -Force
Add the following lines in configuration file:
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
Run:
Add-Migration Initial
- And finally, run:
Update-Database -Verbose
但是,我遇到了一个错误"There is already an object named 'xxx' in the database."
为了解决这个问题,我在第 5 步之后创建的初始文件中的 Up 方法中注释了代码。这可以防止错误,但数据库中没有任何更改(更新后的实体表仍然像以前一样)。
错误在哪里?预先感谢您的帮助。
这里是我在migration.cs文件中注释的Up方法:
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);
}
这是 migration.cs 文件中的 Down 方法:
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-4 步?那是你出错的地方。如果您有一个以前生成的数据库,而您只是对模式进行更改,那么只需生成一个迁移并应用它。通过执行步骤 1-4,您实际上是在撤消 Entity Framework 对该数据库的了解,并且基本上以现有数据库的代码优先结束。在这一点上,您要么必须手动更改您的模式,要么让 Entity Framework 将其破坏并重新开始。
就返回到可以再次应用迁移的状态而言,您在正确的轨道上生成了迁移并清空了 Up
方法。但是,您需要针对应用程序的先前状态执行此操作,即与当前数据库匹配的状态。否则,Entity Framework 将生成包含您的代码更改的创建表。所以要遵循的步骤是:
- 将代码恢复到开始修改 POCO 之前的状态。
- 生成迁移。
- 删除
Up
方法中的所有内容
- 使用
update-database
应用迁移
- 重新应用您对 POCO 所做的更改。
- 生成另一个迁移(这个迁移现在应该只有 add/alter 列语句而不是创建表)
- 应用迁移。
在那之后,你应该可以再去一次。然后,下次更改代码时,只需按照步骤 5 和 6 即可。
我遇到过这个问题。似乎值得注意的是,有一些命令可以帮助解决这种情况,即 -IgnoreChanges 和 -Force 标志。
我正在从多 dbContext 应用程序调整到单 dbContext 应用程序。您可以猜到这些表已经存在,但是在第二个上下文中维护的表的单个上下文没有任何新内容。
它实际上很简单(尽管我花了 2 天时间寻找答案无济于事让我阅读了 command lines of EF Code First Migrations and the package manager...)这是我处理它的方法。
您可以删除 SQL 中的 migrations 文件夹和 _Migrations Table…这将导致您需要使用以下内容:
启用迁移 -Force
但是你应该可以在不采取激烈措施的情况下从这里取货:
- Add-migration “Reset” –IgnoreChanges –Force(强制忽略您的 model/class 中可能存在的更改 – 有利于开始使用现有数据库)
- Update-Database(只写迁移行作为基础)
- Add-migration “AddMyMigrationsToThisDb” –Force(强制迭代代码中的对象模型以获取更改)
- 更新数据库
现在您应该回到正轨,只使用 Add-Migration 和 Update-Database 而没有额外的标志。
在我的 MVC 应用程序中,我使用了 Entity Framework6 并使用代码优先方法创建了数据库。一段时间后,我通过添加新列并删除一些列来更新实体 类 之一。为了将这些更改反映到数据库中,我按照以下步骤操作:
- Deleted the migrations folder in the project.
- Deleted the __MigrationHistory table in the database.
Then run the following command in the Package Manager Console:
Enable-Migrations -EnableAutomaticMigrations -ForceAdd the following lines in configuration file:
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;Run:
Add-Migration Initial- And finally, run:
Update-Database -Verbose
但是,我遇到了一个错误"There is already an object named 'xxx' in the database."
为了解决这个问题,我在第 5 步之后创建的初始文件中的 Up 方法中注释了代码。这可以防止错误,但数据库中没有任何更改(更新后的实体表仍然像以前一样)。 错误在哪里?预先感谢您的帮助。
这里是我在migration.cs文件中注释的Up方法:
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);
}
这是 migration.cs 文件中的 Down 方法:
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-4 步?那是你出错的地方。如果您有一个以前生成的数据库,而您只是对模式进行更改,那么只需生成一个迁移并应用它。通过执行步骤 1-4,您实际上是在撤消 Entity Framework 对该数据库的了解,并且基本上以现有数据库的代码优先结束。在这一点上,您要么必须手动更改您的模式,要么让 Entity Framework 将其破坏并重新开始。
就返回到可以再次应用迁移的状态而言,您在正确的轨道上生成了迁移并清空了 Up
方法。但是,您需要针对应用程序的先前状态执行此操作,即与当前数据库匹配的状态。否则,Entity Framework 将生成包含您的代码更改的创建表。所以要遵循的步骤是:
- 将代码恢复到开始修改 POCO 之前的状态。
- 生成迁移。
- 删除
Up
方法中的所有内容 - 使用
update-database
应用迁移
- 重新应用您对 POCO 所做的更改。
- 生成另一个迁移(这个迁移现在应该只有 add/alter 列语句而不是创建表)
- 应用迁移。
在那之后,你应该可以再去一次。然后,下次更改代码时,只需按照步骤 5 和 6 即可。
我遇到过这个问题。似乎值得注意的是,有一些命令可以帮助解决这种情况,即 -IgnoreChanges 和 -Force 标志。
我正在从多 dbContext 应用程序调整到单 dbContext 应用程序。您可以猜到这些表已经存在,但是在第二个上下文中维护的表的单个上下文没有任何新内容。
它实际上很简单(尽管我花了 2 天时间寻找答案无济于事让我阅读了 command lines of EF Code First Migrations and the package manager...)这是我处理它的方法。
您可以删除 SQL 中的 migrations 文件夹和 _Migrations Table…这将导致您需要使用以下内容: 启用迁移 -Force
但是你应该可以在不采取激烈措施的情况下从这里取货:
- Add-migration “Reset” –IgnoreChanges –Force(强制忽略您的 model/class 中可能存在的更改 – 有利于开始使用现有数据库)
- Update-Database(只写迁移行作为基础)
- Add-migration “AddMyMigrationsToThisDb” –Force(强制迭代代码中的对象模型以获取更改)
- 更新数据库
现在您应该回到正轨,只使用 Add-Migration 和 Update-Database 而没有额外的标志。