Using the Code First approach when building ASP.Net applications with Entity Framework
In this post I would like to show you a hands-on example on how to use the Code First approach when building data-centric ASP.Net applications with EF.
Obviously I cannot go into much detail on what EF is and what it does. I
will give again a short introduction.The .Net framework provides
support for Object Relational Mapping through 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.
You can search in my blog, because I have posted many posts regarding ASP.Net and EF.
I assume you have a working knowledge of C# and know a few things about EF. In order to follow along you must install the Ef 4.1 version from here.
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.
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 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; } public List<Training> Trainings { get; set; } }
5) Now we need to create the Training class. Add a new class to your application and place it in the CodeFirst folder.The code for the class follows.
public class Training { public int TrainingID { get; set; } public int TrainingDuration { get; set; } public string TrainingLocation { get; set; } }
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; } public DbSet<Training> Trainings { 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=.\SqlExpress;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) Now you might wonder where the database is.I will create it now.Go to the Server Explorer and add a new connection. Connect to the local instance of the SQL Server Express edition and you will find the FootballTraining database.Then click OK.See the picture below
11) Now if you expand the database you will see the tables created from the classes. The tables are empty of course and we need to populate them.
Have a look at the picture below to see the tables generated.
Right-click on the Footballers table and select Show Table Data. Input some sample data.
12) Build and Run your application. If you followed all the steps correctly you will see the data in the Gridview.
13) Now I would like to show you what happens when the classes change. When the classes change that will have a profound effect on the generated tables.
Note that we have another table EdmMetadata.It provides a hash field that represents our model classes and stores that value which is used to track all the changes.
14) Let's make a change (add another field to our Footballer class). I will add the "JoinedTheClub" property. The code for the updated class 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; } public DateTime JoinedTheClub { get; set; } public List<Training> Trainings { get; set; } }
15) Now if you run the application again you will get a nasty error.We expected that.Let's fix that.Now we need to tell our application what will do when the model changes as far as the database is concerned.Add a new item in your application a Global.asax file.In this file we have a set of special methods that are called when something happens.
In the Application_Start event handler routine (runs when the application starts) we will add this code
protected void Application_Start(object sender, EventArgs e) { Database.SetInitializer(
new DropCreateDatabaseIfModelChanges<FootballerDBContext>()); }
So if a change in the model occurs, we instruct our application to drop and recreate the database.If you go and see your Footballers table again, the JoinedTheClub column will be there.
If you run your application again, you will not get any error but you will not see any data either.The database was dropped and recreated and wiped all the data.
16) Let's create a new class and add it in the CodeFirst folder. I will call it FootballerInsert.cs. The code for this class follows
The code for the class follows
public class FootballerInsert:
DropCreateDatabaseIfModelChanges<FootballerDBContext>
{ protected override void Seed(FootballerDBContext context) { var footballers = new List<Footballer> { new Footballer { FirstName = "Steven",LastName="Gerrard", Height=1.85,
Weight=85, JoinedTheClub=DateTime.Parse("12/12/1999"), Trainings = new List<Training> { new Training {TrainingDuration = 3, TrainingLocation="MelWood"}, new Training {TrainingDuration = 2, TrainingLocation="Anfield"}, new Training {TrainingDuration = 2, TrainingLocation="MelWood"}, } }, new Footballer { FirstName = "Jamie",LastName="Garragher", Height=1.89,
Weight=89, JoinedTheClub=DateTime.Parse("12/02/2000"), Trainings = new List<Training> { new Training {TrainingDuration = 3, TrainingLocation="MelWood"}, new Training {TrainingDuration = 5, TrainingLocation="Anfield"}, new Training {TrainingDuration = 6, TrainingLocation="Anfield"}, } } }; footballers.ForEach(foot => context.Footballers.Add(foot)); base.Seed(context); } }
Do not forget to add (using System.Data.Entity;) in the beginning of the class file.
In this class I inherit from the DropCreateDatabaseIfModelChanges<FootballerDBContext> class and I will override the default behaviour of that class with my class.
I will ovverride the Seed method with some data.Then I create 2 instances of the Footballer entity and 6 entities of the Training entity.
Then through a simple lambda expression I add the data to the database using this last line of code,
base.Seed(context);
17) Now we need to make one more change.in the Global.asax.cs file change this line of code
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<FootballerDBContext>());
with this one
Database.SetInitializer(new FootballerInsert());
We should initialise with our custom class FootballerInsert and not the DropCreateDatabaseIfModelChanges<FootballerDBContext>
Run your application. You will see no data appearing. If you look in the database tables there will be no data. You probably wondering why is that.
If you think what the FootballerInsert class does, you will see why there is no data appearing on the page and why there is no data in the database.
The FootballerInsert class will drop and create the database only when the model changes. Well, there is no change in our model. So let's make a change to or model, by going to the Footballer class and add a new property (Age). The code for the class 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; } public DateTime JoinedTheClub { get; set; } public int Age { get; set; } public List<Training> Trainings { get; set; } }
18) Run your application and you will see that the page will fill with data. Go to the Server Explorer and open the connection to the database and see the data in the database.
You will also see the Age field added to the Footballers table.I hope you do not find the whole processs too confusing. Just follow the steps and try to make sense of every step.
Email me if you need the source code.
Hope it helps !!!