【问题标题】:How to describe details of an automatic migration如何描述自动迁移的详细信息
【发布时间】:2016-01-08 11:36:59
【问题描述】:

在Entity Framework Code-First中,您可以根据模型中的代码更改启用自动迁移。

通过调用Update-Database,这些更改是:

  1. 注册在[timestamp]_AutomaticMigration
  2. 生成 SQL 脚本并迁移数据库
  3. 将迁移存储在 __MigrationHistory 表中

在__MigrationHistory 表中,迁移在模型列中被描述为一个较大的十六进制值。例如:

0x1F8B0800000000000400CD57CD6EDB3810BE2FB0EF20F0B40512313F976D20B5C8CAC9C2D83A09AAB4775A1ADBC492944A5281FD6C3DF491FA0A1D...

在 Visual Studio 的包管理器控制台中,您可以使用 Get-Migrations 检索自动迁移列表。

但是,似乎没有办法检索特定自动迁移的详细信息——无论是 SQL 脚本,还是受影响的模型和字段。

是否有一种我不知道的方法可以检索特定自动迁移的详细信息?

【问题讨论】:

    标签: c# .net ef-code-first entity-framework-6 automatic-migration


    【解决方案1】:

    是的,有。

    表 __MigrationHistory 中的此值是一个 GZiped Xml,其中包含 EDMX 架构。

    我编写了以下代码来检索 EDMX 模型(此代码使用 C# 6)

    您也可以通过以下链接访问我的 gist 上的此代码:https://gist.github.com/AlbertoMonteiro/45198dc80641ce1896e6

    在这个要点中有一个 C# 5 版本,您可以将其粘贴到控制台应用程序中。

    #r "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Data.dll"
    #r "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Xml.Linq.dll"
    using System.Xml.Linq;
    using System.IO.Compression;
    
    public void DecompressDatabaseMigration(string migrationName, string databaseName)
    {
        var connectionString = $@"Data source=.\sqlexpress;Initial catalog={databaseName};Integrated security=true";
        var sqlToExecute = String.Format("select model from __MigrationHistory where migrationId like '%{0}'", migrationName);
    
        using (var connection = new SqlConnection(connectionString))
        {
            connection.Open();
    
            var command = new SqlCommand(sqlToExecute, connection);
    
            var reader = command.ExecuteReader();
            if (!reader.HasRows)
            {
                throw new Exception("Now Rows to display. Probably migration name is incorrect");
            }
    
            while (reader.Read())
            {
                var model = (byte[])reader["model"];
                var decompressed = Decompress(model);
                File.WriteAllText(@"C:\temp\edmx.xml", decompressed.ToString());
            }
        }
    }
    
    public XDocument Decompress(byte[] bytes)
    {
        using (var memoryStream = new MemoryStream(bytes))
        {
            using (var gzipStream = new GZipStream(memoryStream, CompressionMode.Decompress))
            {
                return XDocument.Load(gzipStream);
            }
        }
    }
    
    DecompressDatabaseMigration(Args[1], Args[0]);  
    

    如您所见,Visual Studio Update 1 附带的新 C# REPL 中允许使用某些语法。

    所以我用.csx 扩展保存这个文件,然后我执行,在我的例子中是DecompileMigration.csx

    csi DecompileMigration.csx
    

    然后脚本会将文件 emdx.xml 放入我的 C:\temp 文件夹中,然后我会在此特定迁移中看到模型。

    要使用VS 2015 update 1的REPL,可以

    加载名为 VS2015 的开发人员命令提示符的自定义 CMD

    按 Windows,然后搜索此名称 VS2015 的开发人员命令提示符

    选项 1

    在 C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio 2015\Visual Studio Tools 中打开它

    选项 2

    打开一个 cmd 会话,然后执行以下命令

    call "%vs140comntools%vsdevcmd.bat"
    

    选项 3

    在Visual Studio 2015 U1的菜单VIEW > Other Windows > C# Interactive中打开它

    如果您使用此选项,则脚本中的 Args 成员将不起作用,因此您必须将 Args[0] 替换为您的数据库名称,并将 Args[0] 替换为您的数据库名称。

    【讨论】:

    • 非常感谢阿尔贝托的回答!我想它会帮助遇到这个问题并且别无选择只能使用自动迁移的其他人(例如,对于具有迁移的现有系统)
    • @Jono 我总是使用手动迁移,但有时我遇到了问题,我执行Update-Database 并收到一条消息说没有待处理的迁移,但是当我运行代码时,我有一个例外,模型被改变了。所以我尝试创建一个新的迁移,迁移是空的,所以我必须启用自动迁移,然后我使用该方法并发现发生了什么变化,我发现是一个 dll 版本导致了这种情况。所以这是“调试”迁移的好方法。
    【解决方案2】:

    这个问题来自自动迁移与显式迁移之间的误解。

    我认为显式迁移需要您编写所有上/下更改。

    Add-Migration 带有迁移更改,否则这些更改会被自动迁移自动放入显式迁移文件中。

    在显式迁移后调用 Update-Database 将迁移更改,但现在使用代码文件详细说明更改。

    【讨论】:

    • 啊,我刚刚回答了如何获取自动迁移的详细信息
    猜你喜欢
    • 2019-10-05
    • 2021-07-12
    • 2021-06-28
    • 1970-01-01
    • 2015-03-03
    • 2018-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多