18

显然 IMigrationMetadata.Target 编码了 EF 模型的状态。我可以使用它来重建特定迁移的模型吗?

4

4 回答 4

31

是的,有可能。我自己很好奇那些魔法资源字符串到底存储了什么。通过深入研究 Entity Framework 源代码(参见DbMigrator.GetLastModel()方法),我发现它IMigrationMetadata.Target只是存储了一个包含 gzip 压缩 XML 数据的 base-64 字符串。为了测试这一点,我创建了一个新的控制台应用程序,其中包含一个简单的代码优先模型,定义如下:

public class ContactContext : DbContext
{
    public virtual IDbSet<Contact> Contacts { get; set; }
}

public class Contact 
{
    public int Id {get; set;}
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

然后我使用 NuGet 包管理器控制台创建了一个迁移:

PM> Enable-Migrations
PM> Add-Migration MyMigration

接下来,我将以下代码添加到我的应用程序的Main()方法中,以解码该字符串中的值并将其转储到控制台:

var migration = new MyMigration();
var metadata = (IMigrationMetadata)migration;
var compressedBytes = Convert.FromBase64String(metadata.Target);
var memoryStream = new MemoryStream(compressedBytes);
var gzip = new GZipStream(memoryStream, CompressionMode.Decompress);
var reader = new StreamReader(gzip);
Console.WriteLine(reader.ReadToEnd());

这将输出一个 EDMX 文件DbContext,该文件表示与创建迁移的我相关联的实体数据模型。如果我将此输出写入具有.edmx扩展名的文件,我可以使用 Visual Studio 打开它并在实体设计器中查看它。

然后,如果出于某种原因我想重新生成DbContext生成模型的实体类,我只需要执行以下操作:

  1. .edmx文件添加到 Visual Studio 项目。
  2. 如果我还没有,请安装适用于 C# 的 EF 5.x DbContext Generator 。
  3. Add -> New Item通过从项目节点上下文菜单中选择来添加相关的 T4 模板。
  4. 修改新添加的.tt文件,替换$edmxInputFile$为我的.edmx文件名。
  5. 看着这两个模板神奇地将我的代码优先类型重新生成到它们各自的.cs文件中。

希望这能回答你的问题!:-D

于 2013-03-30T19:04:05.173 回答
5

我创建了一个小型控制台应用程序,用于从 __MigrationHistory 表https://github.com/andreydil/EfMigrationModelDecoder的 Model 列导出 EDMX
您可以使用参数选择特定的迁移/migration,即:

EfMigrationModelDecoder.Cli.exe "<connectionString here>" /migration:Init
于 2015-06-10T11:25:30.337 回答
4

我创建了一个 PowerShell 脚本来提取从数据库到 edmx 文件的最新迁移。

https://gist.github.com/otto-gebb/93d021c8fd300646dba0073a77585a94

于 2017-07-28T23:57:19.127 回答
0

您还可以使用 SQL...

SELECT CONVERT(xml, DECOMPRESS(Model)) FROM [dbo].[__MigrationHistory] WHERE MigrationId = 'NameOfMigration'
于 2020-05-06T12:34:34.830 回答