Looking into Entity Framework Code First Migrations
Posted
by nikolaosk
on ASP.net Weblogs
See other posts from ASP.net Weblogs
or by nikolaosk
Published on Tue, 20 Nov 2012 08:36:00 GMT
Indexed on
2012/11/21
5:01 UTC
Read the original article
Hit count: 588
In this post I will introduce you to Code First Migrations, an Entity Framework feature introduced in version 4.3 back in February of 2012.
I have extensively covered Entity Framework in this blog. Please find my other Entity Framework posts here .
Before the addition of Code First Migrations (4.1,4.2 versions), Code First database initialisation meant that Code First would create the database if it does not exist (the default behaviour - CreateDatabaseIfNotExists).
The other pattern we could use is DropCreateDatabaseIfModelChanges which means that Entity Framework, will drop the database if it realises that model has changes since the last time it created the database.
The final pattern is DropCreateDatabaseAlways which means that Code First will recreate the database every time one runs the application.
That is of course fine for the development database but totally unacceptable and catastrophic when you have a production database. We cannot lose our data because of the work that Code First works.
Migrations solve this problem.With migrations we can modify the database without completely dropping it.We can modify the database schema to reflect the changes to the model without losing data.
In version EF 5.0 migrations are fully included and supported. I will demonstrate migrations with a hands-on example.
Let me say a few words first about Entity Framework first. The .Net framework provides support for Object Relational Mappingthrough EF. So EF is a an ORM tool and it is now the main data access technology that microsoft works on. I use it quite extensively in my projects. Through EF we have many things out of the box provided for us. We have the automatic generation of SQL code.It maps relational data to strongly types objects.All the changes made to the objects in the memory are persisted in a transactional way back to the data store.
You can find in this post an example on how to use the Entity Framework to retrieve data from an SQL Server Database using the "Database/Schema First" approach.
In this approach we make all the changes at the database level and then we update the model with those changes.
In this post you can see an example on how to use the "Model First" approach when working with ASP.Net and the Entity Framework.
This model was firstly introduced in EF version 4.0 and we could start with a blank model and then create a database from that model.When we made changes to the model , we could recreate the database from the new model.
The Code First approach is the more code-centric than the other two. Basically we write POCO classes and then we persist to a database using something called DBContext.
Code First relies on DbContext. We create 2,3 classes (e.g Person,Product) with properties and then these classes interact with the DbContext class we can create a new database based upon our POCOS classes and have tables generated from those classes.We do not have an .edmx file in this approach.By using this approach we can write much easier unit tests.
DbContext is a new context class and is smaller,lightweight wrapper for the main context class which is ObjectContext (Schema First and Model First).
Let's move on to our hands-on example.
I have installed VS 2012 Ultimate edition in my Windows 8 machine.
1) Create an empty asp.net web application. Give your application a suitable name. Choose C# as the development language
2) Add a new web form item in your application. Leave the default name.
3) Create a new folder. Name it CodeFirst .
4) Add a new item in your application, a class file. Name it Footballer.cs. This is going to be a simple POCO class.Place this class file in the CodeFirst folder.
The code follows
public class Footballer { public int FootballerID { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public double Weight { get; set; } public double Height { get; set; } }
5) We will have to add EF 5.0 to our project. Right-click on the project in the Solution Explorer and select Manage NuGet Packages... for it.In the window that will pop up search for Entity Framework and install it.
Have a look at the picture below
If you want to find out if indeed EF version is 5.0 version is installed have a look at the References. Have a look at the picture below to see what you will see if you have installed everything correctly.
Have a look at the picture below
6) Then we need to create a context class that inherits from DbContext.Add a new class to the CodeFirst folder.Name it FootballerDBContext.Now that we have the entity classes created, we must let the model know.I will have to use the DbSet<T> property.The code for this class follows
public class FootballerDBContext:DbContext { public DbSet<Footballer> Footballers { get; set; } }
Do not forget to add (using System.Data.Entity;) in the beginning of the class file
7) We must take care of the connection string. It is very easy to create one in the web.config.It does not matter that we do not have a database yet.When we run the DbContext and query against it , it will use a connection string in the web.config and will create the database based on the classes.I will use the name "FootballTraining" for the database.
In my case the connection string inside the web.config, looks like this
<connectionStrings> <add name="CodeFirstDBContext"
connectionString="server=.;integrated security=true;
database=FootballTraining" providerName="System.Data.SqlClient"/> </connectionStrings>
8) Now it is time to create Linq to Entities queries to retrieve data from the database . Add a new class to your application in the CodeFirst folder.Name the file DALfootballer.cs
We will create a simple public method to retrieve the footballers. The code for the class follows
public class DALfootballer { FootballerDBContext ctx = new FootballerDBContext(); public List<Footballer> GetFootballers() { var query = from player in ctx.Footballers select player; return query.ToList(); } }
9) Place a GridView control on the Default.aspx page and leave the default name.Add an ObjectDataSource control on the Default.aspx page and leave the default name. Set the DatasourceID property of the GridView control to the ID of the ObjectDataSource control.(DataSourceID="ObjectDataSource1" ). Let's configure the ObjectDataSource control. Click on the smart tag item of the ObjectDataSource control and select Configure Data Source. In the Wizzard that pops up select the DALFootballer class and then in the next step choose the GetFootballers() method.Click Finish to complete the steps of the wizzard.
Build and Run your application.
10) Obviously you will not see any records coming back from your database, because we have not inserted anything. The database is created, though.
Have a look at the picture below.
11) Now let's change the POCO class. Let's add a new property to the Footballer.cs class.
public int Age { get; set; }
Build and run your application again. You will receive an error. Have a look at the picture below
12) That was to be expected.EF Code First Migrations is not activated by default. We have to activate them manually and configure them according to your needs.
We will open the Package Manager Console from the Tools menu within Visual
Studio 2012.Then we will activate the EF Code First Migration Features by writing the command “Enable-Migrations”.
This adds a new folder Migrations in our project. A new auto-generated class
Configuration.cs is created.Another class is also created [CURRENTDATE]_InitialCreate.cs and added to our project.
The [CURRENTDATE]_InitialCreate.cs is shown in the picture below
13) ??w we are ready to migrate the changes in the database. We need to run the Add-Migration Age command in Package Manager Console
Add-Migration will scaffold the next migration based on changes you have made to your model since the last migration was created.
In the Migrations folder, the file 201211201231066_Age.cs is created.
Have a look at the picture below to see the newly generated file and its contents.
Now we can run the Update-Database command in Package Manager Console .See the picture above.
Code First Migrations will compare the migrations in our Migrations folder with the ones that have been applied to the database. It will see that the Age migration needs to be applied, and run it.
The EFMigrations.CodeFirst.FootballeDBContext database is now updated to include the Age column in the Footballers table.
Build and run your application.Everything will work fine now.
Have a look at the picture below to see the migrations applied to our table.
14) We may want it to automatically upgrade the database (by applying any pending migrations) when the application launches.Let's add another property to our Poco class.
public string TShirtNo { get; set; }
We want this change to migrate automatically to the database.
We go to the Configuration.cs we enable automatic migrations.
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
In the Page_Load event handling routine we have to register the MigrateDatabaseToLatestVersion database initializer.
A database initializer simply contains some logic that is used to make sure the database is setup correctly.
protected void Page_Load(object sender, EventArgs e)
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<FootballerDBContext, Configuration>());
}
Build and run your application. It will work fine.
Have a look at the picture below to see the migrations applied to our table in the database.
Hope it helps!!!
© ASP.net Weblogs or respective owner