Step 1 : Generate your Context, Entities, and Mapping Files
Microsoft has released a visual studio plugin (Entity Framework Power Tools) that will generate POCOs and a context based on an EDMX. This will save you a whole lot of time. Head on over here, and install this plugin.
Once installed, move over to you project, and right click your Project File. There should now be a context menu item, Entity Framework, Select That, and then Reverse Engineer Code First.
Select the database you would like to use to base the reverse engineer process to be based on.
Once you click OK, a folder will be created in your project called Models that contains your new Context, Entities, and Fluent mapping configurations.
Microsoft has released a visual studio plugin (Entity Framework Power Tools) that will generate POCOs and a context based on an EDMX. This will save you a whole lot of time. Head on over here, and install this plugin.
Once installed, move over to you project, and right click your Project File. There should now be a context menu item, Entity Framework, Select That, and then Reverse Engineer Code First.
Select the database you would like to use to base the reverse engineer process to be based on.
Once you click OK, a folder will be created in your project called Models that contains your new Context, Entities, and Fluent mapping configurations.
Step 2: Remove old context, and update the project to use the new context.
Now that you have created all of your new entities and context, the old one can be removed. Delete the EDMX and all associated files (context.tt, etc).
Now that you have created all of your new entities and context, the old one can be removed. Delete the EDMX and all associated files (context.tt, etc).
Step 3: Enable Migrations
As I mentioned before, we are NOT enabling automatic migrations. We are only enabling migrations. This means that we will manually create migrations by using the add-migration syntax in the Package Manager Console.
In the Package Manager Console, Make sure that you set the Default Project to the project that contains your context. Then enter the command Enable-Migrations
You will notice that a Migrations folder has been created with a Configuration.cs file. In the Configuration.cs file, make sure Automatic Migrations is set to false.
As I mentioned before, we are NOT enabling automatic migrations. We are only enabling migrations. This means that we will manually create migrations by using the add-migration syntax in the Package Manager Console.
In the Package Manager Console, Make sure that you set the Default Project to the project that contains your context. Then enter the command Enable-Migrations
You will notice that a Migrations folder has been created with a Configuration.cs file. In the Configuration.cs file, make sure Automatic Migrations is set to false.
Step 4: Create and Set Database Initializer
Create a new class called MyDbInitialzier
using
System.Data.Entity;
using
MyProject.Data.DataAccess.Migrations;
namespace
MyProject.Data.DataAccess.EntityFramework
{
internal
sealed
class
MyDbInitializer : MigrateDatabaseToLatestVersion<MyDbContext, Configuration>
{
}
}
You will notice that I the initializer calss inherits from the MigrateDatabaseToLatestVersion class. It is likely that this is the Initializer behavior that you will want to use if you have an existing database already in production. If you have special circumstances, be sure to review all of the default initializers and/or look into building a custom initializer.
Create a new class called MyDbInitialzier
using System.Data.Entity; using MyProject.Data.DataAccess.Migrations; namespace MyProject.Data.DataAccess.EntityFramework { internal sealed class MyDbInitializer : MigrateDatabaseToLatestVersion<MyDbContext, Configuration> { } } |
You will notice that I the initializer calss inherits from the MigrateDatabaseToLatestVersion class. It is likely that this is the Initializer behavior that you will want to use if you have an existing database already in production. If you have special circumstances, be sure to review all of the default initializers and/or look into building a custom initializer.
Step 5: Implement the new Context
You will want to crack open you web config and replace the old connection string (The one with all of the metadata stuff, with a new connection string. The new connection string should look like any old ADO.NET connection string.
You will now want to replace the references to the old context with the new one. (Shortcut: you could just rename the new one to match the old one’s name).
Note: You may encounter a bit of a gotcha here. Since the new context is of type DbContext and the old one was of type ObjectContext, you may find that some the compiler is complaining about some things. The DbContext is kind of a wrapper for the object context that is meant to be lighter weight, there are things you may be using that are not supported by the db context. You will want to research any of these issues that come up to see if the DbContext can support them. If all else fails, the DbContext can be cast to the ObjectContext if you absolutely need it. (This will result in a performance hit, so use wisely). The syntax for getting the ObjectContext from a DbContext is:
public
class
MyContext: DbContext
{
public
ObjectContext ObjectContext()
{
return
(
this
as
IObjectContextAdapter).ObjectContext;
}
}
You will want to crack open you web config and replace the old connection string (The one with all of the metadata stuff, with a new connection string. The new connection string should look like any old ADO.NET connection string.
You will now want to replace the references to the old context with the new one. (Shortcut: you could just rename the new one to match the old one’s name).
Note: You may encounter a bit of a gotcha here. Since the new context is of type DbContext and the old one was of type ObjectContext, you may find that some the compiler is complaining about some things. The DbContext is kind of a wrapper for the object context that is meant to be lighter weight, there are things you may be using that are not supported by the db context. You will want to research any of these issues that come up to see if the DbContext can support them. If all else fails, the DbContext can be cast to the ObjectContext if you absolutely need it. (This will result in a performance hit, so use wisely). The syntax for getting the ObjectContext from a DbContext is:
public class MyContext: DbContext { public ObjectContext ObjectContext() { return ( this as IObjectContextAdapter).ObjectContext; } } |
Step 6: Create Your Initial Migration
If we tried to run the project right now, the application would encounter an error letting you know that there are pending changes that need to be included in a migration before the application can proceed. We are going to create our initial migration. In the Package Manager Console, enter the command Add-Migration initial
In your Migrations folder, a file should have been created:YYYYYYDDHHMMSSS_initial.cs. This should be a total representation of your entire existing database.
EF keeps track of changes to the data model updating a table in your database called __MigrationHistory (in SystemTables) Since your database is existing already, you do not have this table in your database, so when this migration goes to run, it will attempt to re-create all of the objects in your database. This is bad, and we dont want that. We can use this trick to tell EF to not re-create all of the objects when it attempts to run this migration. In your initial migration class, comment out all of the code in the Up method. That’s it, that’s the whole trick.
public
partial
class
initial : DbMigration
{
public
override
void
Up()
{
// Commented Code Here
}
}
If we tried to run the project right now, the application would encounter an error letting you know that there are pending changes that need to be included in a migration before the application can proceed. We are going to create our initial migration. In the Package Manager Console, enter the command Add-Migration initial
In your Migrations folder, a file should have been created:YYYYYYDDHHMMSSS_initial.cs. This should be a total representation of your entire existing database.
EF keeps track of changes to the data model updating a table in your database called __MigrationHistory (in SystemTables) Since your database is existing already, you do not have this table in your database, so when this migration goes to run, it will attempt to re-create all of the objects in your database. This is bad, and we dont want that. We can use this trick to tell EF to not re-create all of the objects when it attempts to run this migration. In your initial migration class, comment out all of the code in the Up method. That’s it, that’s the whole trick.
public partial class initial : DbMigration { public override void Up() { // Commented Code Here } } |
Step 7: Update the Database
Now is the time to update your database. In the package manager console, enter the command, Update-Database.
This will create the __MigrationHistory table and will record that it ran this initial migration, so moving forward it will view your database as ‘up to date’ with your data model. (If you want to create the database from scratch using code first from now on, you will need to uncomment this migration. It can safely be uncommented after it updates the existing database).
That’s it. You should now be able to run your project. Now you need to regression test everything really well.
Conclusion
By following these steps you should now be fully running on Code First with Migrations. Happy Coding!
Now is the time to update your database. In the package manager console, enter the command, Update-Database.
This will create the __MigrationHistory table and will record that it ran this initial migration, so moving forward it will view your database as ‘up to date’ with your data model. (If you want to create the database from scratch using code first from now on, you will need to uncomment this migration. It can safely be uncommented after it updates the existing database).
That’s it. You should now be able to run your project. Now you need to regression test everything really well.
Conclusion
By following these steps you should now be fully running on Code First with Migrations. Happy Coding!