gpt4 book ai didi

c# - 将 Entity Framework 4.1 数据库迁移到 EF5 进行升级,为新安装创建新数据库

转载 作者:行者123 更新时间:2023-11-30 17:55:42 25 4
gpt4 key购买 nike

我目前正在开发一个应用程序的版本 2,该应用程序具有版本 1 用户的现有代码库,但我还需要向新用户推出新版本(即全新安装)。版本 1 使用 Entity Framework 4.1。版本 2 使用 Entity Framework 5。

我的问题是我需要能够将现有的版本 1 用户升级到版本 2 并将他们的数据库迁移到新版本的架构。新模式添加了一些新表,保留了几个现有表并删除了其他表。

我在旅途中发现 EF4.1 不包含 _MigrationHistory 表。因此,我返回到我的原始版本 1 代码,将其升级到 EF5 并按如下方式运行初始迁移:

Add-Migration Initial -IgnoreChanges

这可以很好地为迁移准备好原始版本 1 (EF4.1) 数据库(即添加 _MigrationHistory 表)。然后我将其移植到我的版本 2 代码中并运行:

Update-Database

创建 _MigrationHistory 表然后我运行:

Add-Migration Version2

它生成一个很好的数据库迁移到版本 2。

如果数据库已经存在于版本 1 模式或版本 2 模式(在后一种情况下不应用迁移),这将完美运行,因为我正在使用以下初始化程序:

Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyDbContext, Configuration>());

但是,如果数据库不存在,Initial 迁移会成功运行,但 Version2 迁移会失败,因为某些迁移步骤会删除表、索引和显然不存在于空数据库中的外键。

所以我完全不知所措——如何将现有的版本 1 用户迁移到版本 2(并保留他们的数据),同时还支持需要完全从头开始创建数据库的新安装?

我见过很多关于创建和运行 SQL 脚本以进行迁移的想法,但我确实需要在我的应用程序启动时自动完成此操作。最终用户实际上只需要运行一个 MSI 文件就可以升级。

更新:以下是 w.brian 建议的解决方案(抱歉,我还不能投票):

string connectionString = ConfigurationManager.ConnectionStrings["DbContext"].ConnectionString;
if (Database.Exists(connectionString))
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<DbContext, Migrations.Configuration>());
}
else
{
Database.SetInitializer(new DefaultDataInitialiser());
}

UPDATE2:以上内容似乎是第一次通过新创建工作。但是,下一次运行会通过 Database.Exists() 检查并尝试迁移数据库。但是,由于 _MigrationHistory 表中只有一个条目(由新安装/全新安装生成)并且迁移有两个条目(一个用于 EF4.1 迁移;一个用于新架构) ,迁移逻辑从头开始并尝试应用每个迁移。

这失败了,因为它试图创建已经存在于数据库中的表——它创建这些表是全新安装的一部分!

所以问题的症结在于,这种方法搞乱了迁移逻辑。

UPDATE3:所以我想我已经弄清楚了如何创建初始数据库并允许后续运行仅应用迁移。从上面开始,如果数据库已经存在,则继续迁移代码。

如果数据库尚不存在,请使用 DefaultDataInitialiser 并在 Seed() 方法中执行以下操作:

context.Database.ExecuteSqlCommand(@"DELETE FROM [__MigrationHistory]");

byte[] version1Model = ConvertHexStringToByteArray("1F8B...");
context.Database.ExecuteSqlCommand(@"INSERT INTO [__MigrationHistory]
([MigrationId]
,[Model]
,[ProductVersion])
VALUES
('201302082120145_Initial'
,{0}
,'5.0.0.net40')", new object[] { version1Model });

byte[] version2Model = ConvertHexStringToByteArray("1F8B...");
context.Database.ExecuteSqlCommand(@"INSERT INTO [__MigrationHistory]
([MigrationId]
,[Model]
,[ProductVersion])
VALUES
('201302082200350_Version-2'
,{0}
,'5.0.0.net40')", version2Model);

从迁移逻辑的角度来看,这使新数据库“完全迁移”。下次应用程序运行时,数据库存在并且 MigrateDatabaseToLatestVersion 魔术运行,看到数据库处于最新版本(或在未来升级到下一次迁移)并且很高兴。

不幸的是,将来从头开始创建数据库时,每次新的迁移都需要添加到此 Seed() 方法中。

我从哪里得到用于模型的十六进制字符串?我从 SQL Server Management Studio 从数据库的迁移版本复制了它。

最佳答案

我只会在升级时使用 MigrateDatabaseToLatestVersion 初始值设定项,而不是在新安装时使用。这将要求您直接查询 SQL Server 以查看数据库是否存在,但我认为这应该不会太难,因为您可以访问连接字符串。

关于c# - 将 Entity Framework 4.1 数据库迁移到 EF5 进行升级,为新安装创建新数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14791942/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com