显然,IMigrationMetadata.Target 编码了 EF 模型的状态。我能否使用它来重构特定迁移的模型?
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
和实体类,我只需要执行以下操作:
.edmx
文件添加到 Visual Studio 项目中。Add -> New Item
来添加相关的 T4 模板。.tt
文件,用我的 .edmx
文件的名称替换 $edmxInputFile$
。.cs
文件。希望这回答了你的问题! :-D
我创建了一个小型控制台应用程序,用于从__MigrationHistory表的Model列中导出EDMX https://github.com/andreydil/EfMigrationModelDecoder
您可以使用/migration
参数选择特定的迁移,例如:
EfMigrationModelDecoder.Cli.exe "<connectionString here>" /migration:Init
你也可以使用SQL...
SELECT CONVERT(xml, DECOMPRESS(Model)) FROM [dbo].[__MigrationHistory] WHERE MigrationId = 'NameOfMigration'