我能否从指定的迁移中解码EntityFramework模型?

18
显然,IMigrationMetadata.Target 编码了 EF 模型的状态。我能否使用它来重构特定迁移的模型?

+1,我们希望避免自动运行迁移,而是在管理员调用它们时运行它们,因此我们需要能够从当前迁移重构模型。 - Andrew Stanton-Nurse
1
你能详细说明一下吗?比如你想在哪里和何时重构模型?你想解决什么问题? - Gert Arnold
4个回答

31
是的,这是可能的。我自己也很好奇那些神奇的资源字符串到底存储了什么。通过深入研究实体框架源代码(请参见DbMigrator.GetLastModel()方法),我发现IMigrationMetadata.Target只是存储了一个包含gzipped XML数据的base-64字符串。为了测试这一点,我创建了一个新的控制台应用程序,其中包含一个简单的Code First模型定义如下:
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());

这个生成一个与我的DbContext关联的实体数据模型(Entity Data Model)的EDMX文件。如果我将此输出写入带有.edmx扩展名的文件中,我就可以在Visual Studio中打开它并在实体设计器中查看它。

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

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

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


1
很酷。现在我只需要想一个实际的应用程序:D - Tim Lovell-Smith
1
很棒的东西@luksan,谢谢!对于任何感兴趣的人,我创建了一个小Gist,可以从目标哈希中提取EDMX并再次压缩它:https://gist.github.com/gligoran/87fe3e8eadf5db97ad03。当我需要更改迁移而不干扰其余链时,我使用它。我从我的更改迁移中提取EDMX,编辑XML并将其压缩以获得新的目标。然后,我必须为跟随更改的每个迁移执行此操作。 - gligoran

5

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

EfMigrationModelDecoder.Cli.exe "<connectionString here>" /migration:Init

4

2

你也可以使用SQL...

SELECT CONVERT(xml, DECOMPRESS(Model)) FROM [dbo].[__MigrationHistory] WHERE MigrationId = 'NameOfMigration'

我在我的MSSQL 2008上尝试了这个,但它不起作用。警告:'DECOMPRESS'不存在。你使用的是哪个版本的SQL Server? - FranklinLee
1
SQL Server 2016及更高版本。抱歉,我已经很久没有见过SQL 2008服务器了。 - Prisoner ZERO

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