In this blog I take a look at Microsoft Entity Framework 5 and some of its features. Also, I’ll examine AutoMapper and implement a generic Repository Pattern.
Entity Framework 5 is the latest release of Microsoft’s ORM for .NET. It’s an object-relational mapper that enables .NET developers to work with relational data using domain-specific objects. Entity Framework allows you to work with one of three different workflows but each give the same end result.
You define your domain model using POCO (Plain Old CLR Object) classes, which have no dependency on Entity framework. In this case you need no .edmx file as the mapping will be on the fly using convention over configuration feature in the entity framework
You build your model first using Visual Studio model designer based on the business domain, adding all the business entities and their logical relationships to each other and later you can generate the classes and also the database from that model.
You build the database and reverse engineer it to generate the classes (entities) and its mapping (.edmx file in xml format to map all database tables, views and stored procedures into classes, methods and properties).
Each workflow allows you to approach the solution in a different manner. My personal preference to developing a solution is to clearly define and map out the data model as part of the system requirements. This then allows me to build the database which I will use as the input to the Database First Entity Framework workflow.
For this I’m going to create a console application in Visual Studio 2012.
I’ll be adding a number of separate project layers to the solution which consist of the following:
Infrastructure Layer – This is where the Entity Framework components will reside. This layer will interact directly with the database – In this case SQL Server.
Repository Layer – This is the implementation of the repository pattern. This decouples the infrastructure layer from the layer above and allows for unit testing and for any changes in the infrastructure layer to have a minimal impact on the layers above. E.g. changing the database provider.
Model Layer – This layer holds the domain models which in this example will be POCO (Plain Old CLR Objects) classes. These will just hold public properties for each of our domain entities.
Console application – This is the primary project which is dependent on the above layers. In this example we will just be retrieving some data from the database.
A dependency graph for the solution can be seen below which gives a visual representation of the structure.
Step by Step
Firstly, I’ll create the database in SQL Server 2012. For this example I’m going to use a typical business domain of Customers and Orders. The schema ends up as follows:
As part of defining the above tables I’ve also defined primary keys and relationships between the tables. This will all translate into a well-defined model when the schema is reverse engineered into Entity Framework.
Next, in Visual Studio I’ve created a layered application. The infrastructure layer is where I’m going to add Entity Framework and database context.
To do this you need to Manage NuGet packages and search for Entity Framework.
Install this and it will be added to the infrastructure project.
Next, add an ADO.NET Entity Framework Datamodel to the infrastructure project. This will allow you to create a model using the model designer tools (model first) or in this case to reverse engineer an existing database in to a model.
When prompted, select Generate from database
The model is created and ends up as follows:
Note the Navigation properties which were automatically created. These can be used to refer to related data (see later).
Next, I’m going to define an interface and implementation for the newly created DbContext object in Entity Framework. This is useful when you want to unit test your project.
Next, I’ll add a repository project to the solution. This will decouple the Entity Framework DbContext and entities from the layer that will be consuming them. This will be a generic repository where the type will be passed in.
Next, add a connectionStrings section to the console application config file. You can copy this section from the config file of the infrastructure project which will have been auto-generated when you imported the database model.
In the model project I’ve defined the POCO classes which the Entity Framework entities will map to. Here’s the Customer class:
The virtual property for Orders is optional and is used for automatically loading related data to the customer (see later).
An example of a Retrieve method to retrieve a customer record from the database is as follows:
This creates an instance of our generic repository of type tbCustomer and retrieves a customer record for parameter id. The return statement incorporates a manual mapping between the returned entity from Entity Framework and the business domain POCO object. This is necessary because these are two incompatible objects but can be eliminated by using AutoMapper.
Automatically Retrieving Related Data
In the example solution I mentioned earlier that a virtual property was added to the POCO class. In this case I have added a property with the same name as the desired Navigation property from the model (called Orders).
Using AutoMapper a new map is defined which will map tbOrder to Order
Now, when we retrieve a customer object Entity Framework will automatically map the Orders Navigation property in the model to the POCO property with the same name and initialise it with data. In this case this represents any orders for a given customer.
Updating the Entity Model
Finally, if schema changes are required to the database how do these get reflected in the Entity Framework model?
This is easily achieved by refreshing the database model in the model designer.
First, make your schema changes to the database in SQL Server Management Studio.
Next, open the model .edmx file in Visual Studio.
Right-click anywhere on the design canvas and select “Update model from database”
This presents you with a dialog for automatically adding or refreshing objects in the model from the database.
- Back to Blogs