This post is primarily for my fellow friends of local .net user group who asked for a rough guideline on how to get started with the latest Entity Framework Code First, I will try to keep it short and concise. I assume that it is going to be used in an ASP.NET MVC Application and behind the scene an IoC container would be used to glue everything. Before going into the implementation details there are certain design choice of mine, first persistence ignorance which means the domain model have no clue whether Entity Framework is used or any other ORM (nothing fancy here, out of the box the EF Code First has this support), next, I prefer to use class mapping which I think gives a bit more control comparing to decorating the domain classes with the data annotation attributes. Lets starts with a typical Category, Product, Customer and Order domain.
Each Category can have zero or more products and a Product can also have many categories, the categories also have parent-child relation among them. A Customer can have many orders and an Order has many line items and each line item has associated Product. If you are familiar with the Domain Driven Design (in case if you are not then read this free online book from InfoQ) you already know the terms like Entity, Aggregate Root and Value Objects. In the above, except the Address everything is an Entity and these entities are also Aggregate Root except the OrderLineItem, the Address is a Value Object which embeds into the Customer and Order entity. There are one more convention I will follow that all of the entities should have a Id property which type is Guid. I am not going to post the codes of the above classes since they are pretty basic, only property getters and setters and few shortcut methods to build up the object model properly, in real project this should contain most of the domain logics/business rules.
Now, lets focus on the Data Access part, I will follow the same Repository pattern to persist and retrieve these objects from database, but rather than creating separate repository for each Aggregate Root, I will create a generic repository. Here is the code:
I think most the of the above code is self explanatory, in the constructor I are passing a custom DbContext(which I am going to explain a bit later), then instead of having separate Insert/Update, I only have Save which does both Insert/Update based upon the Id, for the Id generation rather than using Guid.NewGuid(), I am using the NHibernate GuidComb which generates the sequential value, for the timestamp properties I am using the standard Func<> based DateTime so that I can replace the value in the tests. If you are thinking why I am not using the new DateTimeOffset, well the main reason is that it is not supported in the SQL Server Compact Edition which I prefer to use in development and integration tests. Next, all the parameters of the query methods are optional, the One and All also takes an optional includes which is used to eager load the related objects.
Now, lets check how the custom DbContext is implemented. When you are using the class mapping the standard practice is to override the OnModelCreating method and register the mappings, something like the following:
But the problem with this approach is that every time I add/edit/remove the mapping I have to modify this method. Instead, lets automate it, the goal is to collect all the mappings and register it automatically. Here is the actual code of DataContext:
The dictionary in the above constructor holds the generic method of registration as key and class mapping instance as value. Now, I need a factory which should gather all the available mappings and creates this DataContext. Typically in a web application each request should have individual factory and in the lifetime of a request no matter how many times the DataContext is requested the factory would return the same DataContext instance. Here is the DataContextFactory Code:
The DataContextFactory maintains a static dictionary where it uses the connection string name as key and the model builder generic method and class mapping instance as value. The idea is should only scan one for a specific connection string. The matching part is handled in the BuildConfigurations where it only scans the current assembly, in case of domain objects that spans multiple projects you may have to provide a build manager in the DataContextFactory constructor which contains all the assembly references.
Next thing I want to focus is the UnitOfWork, unless the DbContext.SaveChanges() is called, nothing gets sends to to the server. This UnitOfWork should be called by custom action filter, may be in the action executed method. Here is the code of UnitOfWork:
There are one more little thing I need to do before wrapping up the data access, in development and test mode I always need the database schema to be updated according to the domain model but in the production mode I want this feature turned off. (As a side note the EF team is also working on migration support, currently it is in beta, which you should keep an eye on it.)
Usually this code will be executed in the application start, e.g. new SchemaSynchronizer(() => HttpContext.Current.IsDebuggingEnabled).Execute().
Now, everything is set for the integration tests (please note that the above code is written in test first manner, but the primary goal of this post is starting with EF so I kept the test parts in a separate section). As mention in the above that I prefer to use the SQL Server Compact Edition for development/test so I have to add the reference of it’s NuGet package in my test project, other than it I will also add Machine.Specifications(aka MSpec) and AutoPoco NuGet packages in my test project. Next, we have make sure before running the tests our database is synced with the domain model. The MSpec has a hook, the IAssemblyContext interface, the MSpec test runner executes the code written in the OnAssemblyStart and OnAssemblyComplete methods when the test session begins and ends. So, all I have to do is to execute the SchemaSynchronizer when the session starts.
Next, I want to wrap each test in a database transaction and when the test completes rollback the transaction so that it does not interfere with each other result. Unlike, many test frameworks MSpec does not has out of box support for database transaction, but adding such feature is trivial. I will create a base class from which other test classes inherits, the base class with setup the environment for running the tests:
Now, we can write the test to check whether our DataContextFactory is properly configured like this:
Or Repository Tests like:
In the above the ObjectMother is used to create different domain objects, behind the scene it uses the previously added AutoPoco package. I am skipping rest of the Tests but I think you got the idea, now let see how it is integrated with ASP.NET MVC Application. I will be using Ninject in this case but you can use whatever IoC Container you prefer. After adding the Ninject NuGet package the first thing I have to do is create a custom IDependencyResolver which behind the scene uses the Ninject container.
Next, a custom Ninject Module to register the data access components:
and then configure the ASP.NET MVC DependencyResolver.
And finally in application start:
Now, a typical scaffolded controller would look like something like this:
There are one more thing that I have to do before wrapping up this post, remember in the above I mentioned that the UnitOfWork would be Committed in the Action Filter, here is the action filter that does the job:
And then decorating the controller:
And that’s it, I just shown you how to get started with EF quickly yet applying some of the good practices. Obviously this is not silver bullet that you apply in every cases but it is a solid foundation upon which you can add your own modifications. You can get the complete source in the following. Feel free to ask your questions or confusion you may have.