在application_start中使用Fluent Migrator是否可能?

47
我正在使用Fluent Migrator来管理数据库迁移,但我想要做的是在应用程序启动时运行迁移。我最接近的尝试是这样的:
public static void MigrateToLatest(string connectionString)
{
    using (var announcer = new TextWriterAnnouncer(Console.Out)
                                {
                                    ShowElapsedTime = true,
                                    ShowSql = true
                                })
    {
        var assembly = typeof(Runner).Assembly.GetName().Name;

        var migrationContext = new RunnerContext(announcer)
        {
            Connection = connectionString,
            Database = "SqlServer2008",
            Target = assembly
        };

        var executor = new TaskExecutor(migrationContext);
        executor.Execute();
    }
}

我确定以前这个项目是可以运行的,但是已经有一段时间没有看了(这是一个兴趣项目),现在当它到达Execute这一行时,它会抛出空引用异常。不幸的是,这里没有任何文档,我已经努力尝试解决了很长时间。

有人成功地使用FluentMigrator实现了这样的功能吗?


3
我在此记录一下:这个主意不好。将部署/迁移与应用程序的启动绑定在一起?太疯狂了。如果某个迁移失败了,应用程序该怎么办?不启动吗? - jcollum
8
应用程序如果期望已迁移的数据库,那么它能否运行?启动失败是正确的答案。 - Bryan Boettcher
1
@insta 很少。如果应用程序迁移失败,您应立即回滚。应用程序不应知道它处于哪个版本,它只应运行它所拥有的版本。 - jcollum
2
那测试呢?生成一个空数据库来执行集成或验收测试。这是一个有效且有用的场景。 - Bealer
几年过去了,但现在我所做的是:构建服务器运行 SQL 迁移(Redgate 工具),如果失败则还原构建,否则继续部署软件。这对 QA、Live 等也是一样的。本地开发团队使用 Redgate SQL 源代码控制。这被证明是一种稳定的工作方式。 - ilivewithian
2个回答

63

PM> Install-Package FluentMigrator.Tools

手动添加引用:

packages\FluentMigrator.Tools.1.6.1\tools\AnyCPU\40\FluentMigrator.Runner.dll

请注意文件夹名称会因版本号而异,此示例使用当前的1.6.1版本。如果您需要.NET 3.5运行程序,请使用\35\目录。

public static class Runner
{
    public class MigrationOptions : IMigrationProcessorOptions
    {
        public bool PreviewOnly { get; set; }
        public string ProviderSwitches { get; set; }
        public int Timeout { get; set; }
    }

    public static void MigrateToLatest(string connectionString)
    {
        // var announcer = new NullAnnouncer();
        var announcer = new TextWriterAnnouncer(s => System.Diagnostics.Debug.WriteLine(s));
        var assembly = Assembly.GetExecutingAssembly();

        var migrationContext = new RunnerContext(announcer)
        {
            Namespace = "MyApp.Sql.Migrations"
        };

        var options = new MigrationOptions { PreviewOnly=false, Timeout=60 };
        var factory = 
            new FluentMigrator.Runner.Processors.SqlServer.SqlServer2008ProcessorFactory();

        using (var processor = factory.Create(connectionString, announcer, options))
        { 
            var runner = new MigrationRunner(assembly, migrationContext, processor);
            runner.MigrateUp(true);
        }
    }
}

请注意 SqlServer2008ProcessorFactory,这可根据您的数据库进行配置,支持:2000、2005、2008、2012和2014。


我遇到了一个错误,即 TextWriterAnnouncer 没有实现 IDisposable 接口,因此您不能在其上使用 using 语句。这是在最新版本的 FluentMigrator 上发生的。 - Andrew
3
对于任何从NuGet安装FluentMigrator的人来说,FluentMigrator.Runner在工具中,而不是默认引用。 - ashes999
2
FluentMigrator.Runner也在FluentMigrator中。在packages下,有一个tools目录(这是v1.1.1.0的情况)。 - Bealer
1
截至一年前(https://github.com/schambers/fluentmigrator/commit/ccd55287e4934e6ea51e8f1e36bcdd35bdeaf260#L11L25),有一个更改,将IDisposable从“TextAnnouncer”中删除。 相反,如果您遇到文件正在使用的错误,请处理“IMigrationProcessor”。 - bpruitt-goddard
不要忘记安装“FluentMigrator.Tools”包,这是Nuget上的单独项目(因为默认包只有x86运行程序,在AnyCPU项目中会出现BadImageFormatException错误)。 - Yury Schkatula
显示剩余2条评论

5

我曾经在application_start中成功运行迁移,但从那段代码无法判断出问题所在...由于这是开源的,建议您将代码拉到您的解决方案中并构建它以找出Execute方法的问题所在。我发现Fluent Migrator的源代码组织得很好。

如果这是一个Web应用程序,您可能需要担心确保在迁移时没有人使用数据库。我的策略是建立一个连接,将数据库设置为单用户模式,运行迁移,将数据库设置为多用户模式,然后关闭连接。这也处理了负载均衡的Web应用程序在多个服务器上运行的情况,因此2个服务器不会尝试针对同一数据库运行迁移。


有趣的方法来玩单用户模式和多用户模式,以便运行迁移。 - Kat Lim Ruiz
在多台服务器上负载平衡的 Web 应用程序场景下:您可以在部署之前在 Octopus 中创建一个步骤,以在每个服务器上运行迁移。 - Andrey Prokhorov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接