Why does the Entity Framework EF Migrations Add-Migration phase require a database connection string?

I am trying to use and understand EF Migrations (using EF 4.3.1, Code First). To raise a new change, I have to use the following command:

Add-Migration MyMigration -ConnectionString "Data Source=.;Initial Catalog=mydb;" -ConnectionProviderName "System.Data.SqlClient" -StartUpProjectName MyWebsite -ProjectName MyEF.Migrations 

Why is connection string data required for add-migration? Update-Database needs one that makes sense. But doesn't Add-Migration have everything you need from DbContext and configuration?

This is not just idle surprise, it is very confusing to give it a database, because we have a “multi-user” thing where the desired database is flexible and can change from query to query, not to mention static compilation time. Therefore, if Add-Migration actually uses this database for anything, we have a problem.

UPDATE: we abandoned EF Migrations and instead used the Fluent Migrator and are happy. This is much, much faster, even taking into account the fact that we have to write several things twice (once for the EF object and once for the migration), and there are no problems discussed in this issue.

+22
entity-framework-4 ef-migrations
May 29 '12 at 2:33 pm
source share
4 answers

Add-Migration checks for a database and interacts with the __MigrationHistory table. Since @Anders Abel mentioned that it is used to study pending migration, as well as to select the previous model to really find what has changed, this is especially important if you add explicit migration to a solution that allows automatic migrations.

+12
May 29 '12 at 19:35
source share

I was wondering when I read your question, so I activated the Sql Server Profiler to see what happens when add-migration starts. It really connects to the database and accesses the database to check the __MigrationHistory table.

This is also shown by the error message generated when trying to create a second migration based on code without starting the first:

It is not possible to create an explicit transition because the following explicit migrations are expected: [201205291928386_foo]. Apply while waiting for explicit migrations before trying to create a new explicit migration.

I think the migration engine uses a serialized model from the database to calculate which migration steps should be included in the new migration.

As far as I understand, the database is used only as an assistant for code generation. As long as all the databases you use are compatible with the model in code, this should not be a problem for yours.

Edit

As @Ladislav Mrnka notes, checking with the database is required if you mix code and automatic migrations. When you pick up a new migration, it should include everything that has changed in your model since the last migration. If you use automatic migrations, they are not tracked in code. When calculating the changes that need to be included in the transfer, the last migration of the run is used as the base. The only way to verify this is with a database, as automatic migrations can be enabled.

If you only work with code-based migrations (which, I think, is the only option for control), then this database can be considered as just a help for generating code. As long as model compatibility is provided in all the databases to which you connect, everything should work.

+9
May 29 '12 at 19:32
source share

OP wrote (a):

But doesn’t add-Migration has everything you need from DbContext and Configuration?

No - as mentioned above, the part of the manual migration code constructor (created by add-migration ) contains a snapshot of your database schema.

However, the fact that you are using a connection string, etc., is very strange. EF usually implies this from your DbContext and Web.Config classes (s). In a project where I have one database and one DbContext, I create a configuration class and add manual migration with:

 add-migration 

I do not need to pass any other command line arguments. What's in EF 4.3.1 - maybe you used CTP or some older version or just misunderstood the documents?

If I have several DBs or DbContexts, then I have several configuration classes and, for example, use:

 add-migration -conf Log 

Which uses my configuration class and associated connection string in Web.config to add manual migration for this database / DbContext.

Here's a longer sample simple DbContext code for storing logs (separate from the main db):

 namespace MyProj.Models.Log { public class LogDb : DbContext { public DbSet<LogLine> LogLines { get; set; } public DbSet<LogTag> LogTags { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); } } public LogDb() #if DEPLOYDB : base("LogDeploy") #else : base() #endif { } } namespace MyProj.Migrations { internal sealed class Log : DbMigrationsConfiguration<LogDb> { public Log() { AutomaticMigrationsEnabled = true; } } } 

In Web.Config:

 <add name="LogDb" connectionString="Initial Catalog=Log;Data Source=.\SqlExpress;Integrated Security=SSPI;MultipleActiveResultSets=true" providerName="System.Data.SqlClient" /> <add name="LogDeploy" connectionString="Initial Catalog=Log;Data Source=00.00.000.00,12345;User ID=sql;Password=xxx;Network Library=DBMSSOCN" providerName="System.Data.SqlClient" /> 

So, in this example, I have several databases, several DbContexts. LogDb uses a different connection string in Web.Config based on the definition of "DBDEPLOY" at compile time; if so, it uses "LogDeploy". If not, it uses the default value - the connection string with the same name as the class, "LogDb". This allows me to easily deploy database changes to the server from my local computer, switching my project configuration, opening the port on the SQL db machine and running:

 > update-database -conf Log 

in the package manager console.

0
Sep 11
source share

I watched this video of Rowan Miller since March 2014: Migrations - under the hood

In the video, Rowan explains that the Add-Migration command takes several steps that include a component called EdmModelDiffer . EdmModelDiffer compares the current model with the previous model with the last migration (which is embedded in the resx file of the previous migration), and then calculates the necessary changes in the database.

Therefore, the EdmModelDiffer component requires a database connection.

The steps described in the video are as follows:

  • Build current model from code
  • Get previous model from last migration (stored as snapshot in resx file)
  • Calculate the necessary database changes (made by EdmModelDiffer )
  • New migration file generated

Theoretically, it could be assumed that it would be sufficient to compare this current model with the last migration model to generate a new migration. But at the same time, other people could also make changes to the database. This is probably why database validation also exists. Without this, the resulting migration file does not have to be correct.


See also the second video called Migrations - Team Environment

0
Dec 07 '15 at 13:24
source share



All Articles