Entity Framework 6 Code First Migration's ContextKey - entity-framework

Now i'm using EF6 Alpha, and when using migration, it will add a new migration log into the __MigrationHistory table.
In EF6, The __MigrationHistory table has a new column called "ContextKey". After testing, I found there are two default "ContextKey" value:
The full name of DbContext's derived class.This happens when i run the code:
Database.CreateIfNotExists();
The full name of DbMigrationsConfiguration's derived class. This happens when i run the code:
public ArticleDbContext()
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<ArticleDbContext, ArticleConfiguration>());
}
The first time i run the application, "Database.CreateIfNotExists();" create a new database for me, also all tables that map to the models defined in ArticleDbContext, and then add a __MigrationHistory row which ContextKey's value is "Module.Article.Model.ArticleDbContext".
And then "Database.SetInitializer(new MigrateDatabaseToLatestVersion());" will be runned, this code will generate a new ContextKey "PowerEasy.Module.Article.Migrations.ArticleConfiguration". Migration query the __MigrationHistory table with this ContextKey and find out there's no data. So again it will create all tables that map to the models defined in ArticleDbContext, but the tables are already exist in the database, so an exception will be throwed, and tell me "the table XXX is already existed".
How can i solve this?

You should not mix Migrations and the Database.CreateIfNotExists method (or any of the initializers built on top of it). Migrations will take care of creating the database if it does not already exist.
As an alternative to the Migrations initializer, you can also apply migrations using the DbMigrator.Update method. This is useful if you want to create/update the database before it would otherwise be triggered by the initializer.

Related

Dis-Advantages of using EF 6.x.x Code First without Migration

I am fed up of using/running Add-Migration and Update-Database because lot of time we forget to run migrations on production database. So, we decided to delete all migrations from database table as well all migration classes. So, what if my __MigrationHistory table remains always empty and no migration classes. What is the main disadvantage?
No this is a bad idea, the [__MigrationHistory] is used to compare your current used conceptual model with the storage model.
1) Case: DbMigrationsConfiguration automatic:
[__MigrationHistory] keeps track for the last migration.
this.AutomaticMigrationsEnabled = true;
this.AutomaticMigrationDataLossAllowed = true;
as shown in the image above, the migrationId is the migration identifier and the model column is a base64 representation of the binary stream of your current conceptual model.
2) Case: DbMigrationsConfiguration non-automatic:
[__MigrationHistory] keeps track of every migration.
this.AutomaticMigrationsEnabled = false;
this.AutomaticMigrationDataLossAllowed = false;
Each migration level obtain a migrationId identifier which is used for migration level up/level/down.
Best practice: If you want to use the automatic migration just regenerate the migration and shipped to the custmer.
If you are using non-automatic migration.
1) If the customer need the data then just tranform the data with SQL to the new db schema
2) If the customer does not need the data then just drop the database an create it again with initialCreate.
If you want to create the database without any migrationHistory info:
// Create the database. You can generate it from SMO "Script database as" and if the database exist then just ignore the creation
// Do not forget to remove the [__MigrationHistory] rows.
DbContext.Database.ExecuteSqlCommand("SQLCreateDbScript.sql");
Database.SetInitializer<MyDbContext>(null);
using (var dbContext = new MyDbContext())
{
// Create DbContext and it works!
dbContext.Users.Add(new User());
dbContext.SaveChanges();
}
I hope this will help you to solve the problem!
And if you want something really with less Db-Schema then use NoSql with EF.
In Core version still not done but with the old version EF6 it is possible todo that (NoSql Db) with: http://www.brightstardb.com or use the Polyglot appoarch from microsoft https://msdn.microsoft.com/en-us/library/dn271399.aspx

Locating Source of Migration

I have a project that just started using EF Migrations.
There is an initial migration and an additional, hand-edited migration that defines indexed views. There is no other migration.
I recently added a single property to one class. When I create a new schema, the property is created. However, I cannot see why it is created, since the property is not mentioned in any migration.
If I search the entire source code folder (with subfolders, .) for any mention of that property name, it does not appear in any EF migration code (it only appears in the class where it is defined, and in a few lines of code where the property is accessed).
When I set a breakpoint at the beginning and end of the Up() method for the two existing migrations, I can see that the table is created without the additional property by the initial migration (verified in SSMS), and that the property does not yet exist at the end of the last Up() migration. Sometime after control leaves the last migration, some code creates a column in the database for this additional property.
To try and track this down, I hand-edited this new property into the initial migration. Now, after the Up() method for the last migration exits, I get an SqlException
Column names in each table must be unique. Column name 'MyNewProperty' in table 'dbo.MyTable' is specified more than once.
in the constructor for my DbContext.
The stack trace only shows the code that is instantiating DbContext.
How can I track down where this additional migration is coming from?
If you are not explicitly adding a code-based migration for this new property (using add-migration), but a column is being created it can be determined that automatic migrations are enabled.
Automatic migrations allow Entity Framework to automatically determine the schema changes required to represent any changes made to the domain model, this is what is adding your new column.
You are also wondering why it still tries to add the new column even after you hand edit a code-based migration to add this new column; for each code-based migration there is a generated code-behind file (.Designer.cs) which contains a string IMigrationMetadata.Target property, this returns a string snapshot of what the domain model will look like after this migration has been applied.
When you edit the migration file by hand, this Target property still returns the old string representation of the domain, which does not contain your new property; as a result of this, automatic migrations then attempts to add a duplicate column.
The solution to this is to add your new property to the domain then use the add-migration command to add a new code-based migration for this new property.

Ignore existed table when update-database?

I'm using Entity framework 5 code first in an Asp.Net MVC app. The app already created a table UserProfile. I moved the class in a different DbContext and also create some new classes for the DbContext; then I ran enabled-migration, add-migration and update-database. I got the following error when update-database.
There is already an object named 'UserProfile' in the database.
How to let EF-code-first don't generate the creating script for the table? However, I will need EF-code first to track the added columns in the class and update the table later.
Use Update-Database -Script for update a database manually. And you can exclude 'UserProfile' from resulting script.

If I use EF Code First then how can I add another column to a table?

I created POCO classes and then EF created the database tables for me when I tried to access the data. This worked without problem. I have now populated my tables with data. Not just seed data but real data.
Now I would like to add another column to a table. I assume the first thing I need to do is to add a field to the POCO class but what's next after that? I now have my database filled with data. On the SQL side I know how to add the column myself but do I have to do something with EF or will it automatically pick up that my column was added to the table and my field to the POCO class?
You can use Code First Migrations (http://msdn.microsoft.com/en-us/library/hh770484(v=vs.103).aspx). It can update your database automatically or not.

EF Code First: Migrating Database Initialized on Different Code Versions

I am using Entity Framework 5 RC, code first. I am struggling with migrating databases that were created on different versions of code. For example, Database A was created when table FooBar didn't exist. Database B was created after table FooBar was added to my model.
I have a migration written that adds the FooBar table. Is it my responsibility to check in the FooBar migration that the table doesn't exist before calling CreateTable? It seems that is the case since Database B doesn't have an entry for the FooBar migration and will attempt to run it.
At first the MigrationHistory table seemed like it would save me from adding these checks but since new databases won't have entries for migrations added before the database was created, I still need to do the checks myself. Is that the right way to go about it or am I missing something?
To get around an issue I had with adding Stored Procedures, I wrote a TSQL script to create a new table "_PreviousMigrationHistory" - which receives new entries from the "_MigrationHistory" table after my stored procedure scripts have run...
I did add a new column to both tables ( "VersionId", of INT - IDENTITY(1,1) ) which is what I use for comparison within my code.
This way you have the un-updated migration patterns available to you (__PreviousMigrationHistory), even after Code First Migrations have occurred.
Would this help?
**EDIT - sorry, I miss read the question. - Although I would think that new instances of the database would still go through the migration steps, which in turn should add the entries to the __MigrationHistory table?