Apparently IMigrationMetadata.Target encodes the state of the EF model. Can I use this to reconstruct the model for a particular migration?
- +1, we want to avoid running migrations automatically and instead run them when an admin invokes them, so we need to be able to reconstruct a model from whatever the current migration is.Andrew Stanton-Nurse– Andrew Stanton-Nurse2013-03-29 19:14:02 +00:00Commented Mar 29, 2013 at 19:14
- 1Could you elaborate a bit? Like where and when would you like to reconstruct the model? What problem would you like to solve?Gert Arnold– Gert Arnold2013-03-29 21:26:21 +00:00Commented Mar 29, 2013 at 21:26
4 Answers
Yes, it is possible. I was myself curious what exactly those magic resource strings were storing. By digging into the Entity Framework source (see the DbMigrator.GetLastModel() method), I found out that the IMigrationMetadata.Target just stores a base-64 string containing gzipped XML data. To test this, I created a new console application containing a simple code-first model defined as follows:
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; } } Then I created a migration using the NuGet Package Manager Console:
PM> Enable-Migrations PM> Add-Migration MyMigration Next I added the following code to my application's Main() method to decode the value in that string and dump it to the console:
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()); This outputs an EDMX file representing the Entity Data Model associated with my DbContext that created the migration. If I write this output to a file with the .edmx extension, I'm able to open it with Visual Studio and view it in the Entity Designer.
Then if for some reason I wanted to regenerate the DbContext and entity classes that produced the model, I would need only do the following:
- Add the
.edmxfile to a Visual Studio project. - Install the EF 5.x DbContext Generator for C# if I don't already have it.
- Add the related T4 templates by selecting
Add -> New Itemfrom project node context menu. - Modify the newly added
.ttfiles, replacing$edmxInputFile$with the name of my.edmxfile. - Watch as the two templates magically regenerate my code-first types to their respective
.csfiles.
Hope that answers your question! :-D
2 Comments
I created a small console app to export EDMX from the Model column of the __MigrationHistory table https://github.com/andreydil/EfMigrationModelDecoder
You can choose specific migration using /migration parameter, i.e:
EfMigrationModelDecoder.Cli.exe "<connectionString here>" /migration:Init Comments
I created a PowerShell script to extract the latest migration from a DB to a edmx-file.
https://gist.github.com/otto-gebb/93d021c8fd300646dba0073a77585a94
Comments
You can also use SQL...
SELECT CONVERT(xml, DECOMPRESS(Model)) FROM [dbo].[__MigrationHistory] WHERE MigrationId = 'NameOfMigration'