【问题标题】:Manage Entity Framework code first migrations in a setup project在安装项目中管理实体框架代码首次迁移
【发布时间】:2016-10-04 08:26:51
【问题描述】:

我正在使用 Wix 开发安装项目,并且正在使用迁移 .dll 文件安装数据库。

我计划使用 Migrate.exe 从 .dll 执行迁移,但是如果运行更新版本的安装程序(使用更新的迁移),我必须更新数据库。我找不到使用 Migrate.exe 列出所有迁移并仅运行那些尚未针对已安装数据库运行的迁移的方法。

您是否知道使用 Migrate.exe 或任何其他工具或框架来满足此要求的方法,这将允许我跟踪迁移并仅运行那些未针对数据库执行的迁移?

我应该能够在安装程序项目中实现建议的功能以使其正常工作。

谢谢。

最好的问候, 叶夫根尼·杜尔格罗夫

【问题讨论】:

  • 您指的是实体框架代码优先迁移吗?如果是这样,那么在标题或问题本身中添加它是有意义的
  • 是的 - 我添加了它。谢谢。

标签: database wix migration installation code-first


【解决方案1】:

您不需要在安装过程中运行迁移脚本 - 您的安装程序将需要太高的权限才能执行此操作,并且您可能会遇到系统管理员从 Active Directory 应用的安装包策略的问题。

Db 升级也是应用程序逻辑,我相信它属于应用程序 - 而不是安装程序。

当然可以在wix with custom actions 中进行。但是您必须加载迁移所需的所有程序集 - 至少运行 SQL 命令。

我建议您在应用启动时运行迁移。

这是一个可以完成这项工作的片段。首先让我们了解一些上下文:

  1. 您在项目开发周期中创建了 N 个后续迁移。
  2. 您可以使用 Visual Studio 中包管理器控制台中的 EF 工具或直接使用(您可以在 nuget 包中找到的 .exe)来创建部分(更新)迁移。之后,您将在迁移程序集中编译它们,以便通过安装程序将它们与您的应用程序一起带到客户端。一个例子:

    Add-Migration -Name SomeDbChangeDescription -StartUpProjectName TheCoreProjectWithConfig -ProjectName TheProjectWithMigrations -ConfigurationTypeName "Fully.Qualified.Type.Name.Of.MigrationConfiguration" -ConnectionString "Data Source=.\SQLINSTANCE;Database=my-db;Trusted_Connection=False;用户 ID=xxx;密码=xxx" -ConnectionProviderName "System.Data.SqlClient"

请记住,使用此脚本,您可以从一个 db 生成迁移脚本,但您可以稍后将其应用于多个数据库 - 当您拥有 db-per-tenant 时。如果每个数据库源自同一模型,则无需为每个数据库生成迁移脚本,因为在生成过程中迁移脚本中没有硬编码数据库特定信息。

  1. 您编译迁移程序集并确保它在安装程序中并且在应用启动时加载。

现在您可以使用(随意修改)以下代码。 dbMigrator.Update() 将应用所有需要应用的迁移脚本 - 如果您在程序集中有 10 个迁移,其中 2 个未应用迁移,它将比较数据库的模型和所有迁移,并且仅应用最后 2 个。如果您使用不存在的数据库名称调用 dbMigrator.Update() 方法,它将创建应用初始脚本和所有其他部分更新的新数据库。

public class DbInitializer : IDbInitializer
{
    private readonly IConnectionStringProvider _connectionStringProvider;

    public DbInitializer(IConnectionStringProvider connectionStringProvider)
    {
        _connectionStringProvider = connectionStringProvider;
    }

    public void CreateOrUpdateDb(string dbName)
    {
        try
        {
            string connectionString = _connectionStringProvider.GetConnectionString(dbName);
            DbMigrationsConfiguration cfg = CreateMigrationsConfig(connectionString);
            cfg.CommandTimeout = 900;
            cfg.AutomaticMigrationsEnabled = false;
            cfg.AutomaticMigrationDataLossAllowed = false;
            DbMigrator dbMigrator = new DbMigrator(cfg);

            var pendingMigrations = dbMigrator.GetPendingMigrations().ToArray();
            if(pendingMigrations.Length > 0)
            {
                foreach(var pendingMigration in pendingMigrations)
                {
                    InitializerEventSource.Log.UpgradingDb(dbName, pendingMigration);
                }

                dbMigrator.Update();
                DbInitializerEventSource.Log.UpgradedDb(dbName);
            }
        }
        catch(MigrationsException exception)
        {
            // exception handling
        }
        catch(Exception exception)
        {
            // exception handling
        }
    }

    private DbMigrationsConfiguration<InitDbContext> CreateMigrationsConfig(string connectionString)
    {
        DbMigrationsConfiguration<InitDbContext> cfg = new DbMigrationsConfiguration<InitDbContext>
            {
                AutomaticMigrationsEnabled = false,
                AutomaticMigrationDataLossAllowed = false,
                MigrationsAssembly = Assembly.Load("TheAssemblyContainingTheMigrations"),
                MigrationsNamespace = "TheNamespaceWhereTheMigrationsAre",
                ContextKey = "HardCodedContexKey",
                TargetDatabase = new DbConnectionInfo(connectionString, _connectionStringProvider.ProviderInvariantName)
            };
        return cfg;
        }     
}

更新 您可以应用另一种方法 -

  1. 在开发过程中使用上面提到的AddMigration脚本并添加-Script指令来获取SQL迁移脚本而不是C#迁移脚本。
  2. 在安装过程中使用WIX Sql Extension 执行它。 The official Sql Extension for Wix Documentation.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-16
    • 2018-01-29
    • 2014-02-11
    • 2013-12-29
    相关资源
    最近更新 更多