Saturday, May 30, 2009

Entity Framework POCO Repository using Visual Studio 2010 .Net 4.0 Beta 1

Note: This article applies to beta software and comes with no warranty or support, use at your own discretion. You must have Visual Studio.Net 2010 Beta 1 installed on your machine to make use of the code.

Update 25/06/2009: This article should be read first, however, see next article here which uses asp.net mvc and db4o object database with updated code now hosted at codeplex at http://kandaalpha.codeplex.com/
http://blog.keithpatton.com/2009/06/25/db4o+POCO+Repository+Using+Visual+Studio+2010+Net+40+Beta+1+And+ASPNet+MVC+10.aspx

Download KandaAlpha v1 Code Now

Introduction

Before i delve into the details, it’s worth providing a bit of context on this post. For a number of years i’ve been a big fan of ORMs (object relational mappers) for helping get in memory software objects into and out of databases.

I’ve gradually moved away from a data-centric view of the world, towards a transition to domain driven design methodologies in architecting more complex enterprise applications.

My ORM of choice has up until around a year ago been NHibernate. I used it for a few years and grew to love it’s power and flexibility. But it always felt and still is a bit of a black art to make sing. And the tool and Linq support has never really matured to a level where i thought it was really going to take off.

Then along came the Entity Framework from Microsoft. I compared it and NHibernate during the .net 3.5 SP1 beta period and concluded that whilst it was architecturally inferior in many ways to NH, the availability of a designer, integrateion with Visual studio and .net combined with the sheer muscle of Microsoft dollars convinced me to give it a shot.

It was a success and saved me a lot of time, although i did have some pain taking EF across tiers usign web services, although the pain would likely have been there but in a different way with NHibernate. You can see some relatively popular previous posts are related to EF, with the Vote of Confidence in EF (in riposted to Alt.Net’s Vote of No Confidence) and also the code for the Polymorphic Repository for Entity Framework 1.0 (or what is now being called 3.5!).

And now we have Entity Framework 4.0. It is abundantly clear that the EF team have listened, learned and produced an ORM to be proud of. Whilst there will likely be gripes in various camps, we now have full POCO (plain old CLR object) support, lazy (deferred) loading support, AND model first design which allows us to create domain models and have the database generated from that. Very cool indeed.

So that’s the introduction. What i’m attempting to do at this early stage is to clearly demonstrate a DDD inspired layered architecture which combines a Repository pattern, injection of control (IoC) using the Microsoft Unity Application Block (swap out for your favourite IoC) and an Entity Framework 4.0 repository implementation.

The Architecture

Presented below are 4 logical layers, Presentation, Application, Domain and Infrastructure (a good overview of the DDD Layers). The rectangles are logical components within each layer (represented in code as .net assemblies). The full head arrows are runtime dependencies between the various libraries which sit within a particular layer. The dotted lines represent runtime dependency injection via our inversion of control tool of choice.

IMG

The Presentation Layer contains a web application (MVC wasn’t available in the Vs.net 2010 Beta 1 so I just used a ‘normal’ web application).

Then we have an Application Layer which has a class library of interfaces to define the behaviour of the implementing services which are in another class library. The services are injected using IoC as implementations of the application interfaces (we’ll see how that’s done later using Unity). The application layer co-ordinates requests from the presentation layer and makes use of the Repository in doing so.

The Domain Layer contains our Domain Model and Repository. The domain model has no dependencies to any other component or layer. The Repository consists of interfaces which define the behavior of the Repository implemented which is injected using IoC. The Repository represents a ‘store’ view of domain objects, underpinned by some form of persistence framework in the Infrastructure layer.

Lastly we have an Infrastructure Layer. In our example architecture this is the Entity Framework repository implementation and persistence framework. The class library has classes which implement the Domain’s Repository interfaces as well as having dependencies on the core EF classes and libraries.

Overall, this is a relaxed layered architecture in the sense that we have decent separate of concerns between the layers but we do allow cross layer dependencies. For example the domain model types are used within the web application (rather than have an extra layer of interfaces or data transfer objects).

The key point in this architecture is that the means by which domain objects are persisted is separated from the domain objects themselves. In addition, we have a  Repository is defined within the domain layer, whilst its implementation is injected using IoC. The domain layer as a whole therefore has no awareness of or build dependency on the underlying persistence framework.

 

 

 

The Solution

SolutionStructure

Here is the architecture represented as a Visual Studio.Net solution. You can see that I’m using Solution Folders to represent the various layers and then using class libraries for each layer component with the exception of the presentation layer which is represented by an asp.net web application. KandaAlpha is just a sandbox prefix I’m using.

For completeness please do note the Base Libraries folder which simply contains the IoC facade to the Microsoft Unity Application Block and also a references project housing the Unity application block dlls.

 

 

 

 

 

 

The Client Code

This first bit of code is the client api view at the asp.net web application level.

// get the customer service using IoC (Unity)
var custService = IoCWorker.Resolve<ICustomerService>();

// get the customer repository from the customer service
var custRepository = custService.GetRepository();

// get all customers and bind to grid
dgCustomers.DataSource = custRepository.GetAll();
dgCustomers.DataBind();

// use a specific method on customer repository
var kp = custRepository.GetBestCustomer();

// display customer's full name
litCustomerName.Text = kp.FullName;

// demonstrate lazy/deferred loading (not for production!)
litFirstOrderTotal.Text += kp.Orders.First().OrderTotal.ToString();

The basic idea here is that we request a service from the IoC container, and the service then provides the ability to fulfill a particular orchestration or unit of work.

You can see from the code that the ICustomerService implementation allows us to get a repository implementation to get all customers, to get the best customer, and also to get the first order total of the best customer. Note how lazy/deferred loading is working for the last call.

And hey presto, a very exciting screen is produced. (Note that the database is stored within App_Data in the web project. This would obviously be a remote SQL server in a production environment, i just wanted to provide the source fully contained)

FinalPage

Wiring up Unity IoC

Here’s how the inversion of control is wired up. See the containers element were we set up a single container and then set up the container to wire particular class implementations as singletons for each particular interface we are interested in providing a service implementation for. Take a look at the small KandaAlpha.Ioc.IocWorker static facade class which combined with configuration initialises the container and provides the hook into resolving service implementations for interfaces via the Resolve<T>() method.

<unity>
    <typeAliases>
      <!-- Lifetime manager types -->
      <typeAlias alias="singleton"
           type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager,
               Microsoft.Practices.Unity" />
      <typeAlias alias="perThread"
           type="Microsoft.Practices.Unity.PerThreadLifetimeManager,
               Microsoft.Practices.Unity" />
      <typeAlias alias="external"
           type="Microsoft.Practices.Unity.ExternallyControlledLifetimeManager,
               Microsoft.Practices.Unity" />
      <!-- User-defined type aliases -->
      <typeAlias alias="ICustomerService"
      type="KandaAlpha.Application.Interfaces.ICustomerService, KandaAlpha.Application.Interfaces" />
      <typeAlias alias="CustomerService"
           type="KandaAlpha.Application.Services.CustomerService, KandaAlpha.Application.Services" />
      <typeAlias alias="IGenericRepository"
           type="KandaAlpha.Domain.Repository.IGenericRepository`1, KandaAlpha.Domain.Repository" />
      <typeAlias alias="GenericRepository"
           type="KandaAlpha.Infrastructure.Repository.EF.GenericRepository`1, KandaAlpha.Infrastructure.Repository.EF" />
      <typeAlias alias="ICustomerRepository"
           type="KandaAlpha.Domain.Repository.ICustomerRepository, KandaAlpha.Domain.Repository" />
      <typeAlias alias="CustomerRepository"
           type="KandaAlpha.Infrastructure.Repository.EF.CustomerRepository, KandaAlpha.Infrastructure.Repository.EF" />

    </typeAliases>
    <containers>
      <container name="containerOne">
        <types>
          <type type="ICustomerService" mapTo="CustomerService">
            <lifetime type="singleton" />
          </type>
          <type type="IGenericRepository" mapTo="GenericRepository">
            <lifetime type="singleton" />
          </type>
          <type type="ICustomerRepository" mapTo="CustomerRepository">
            <lifetime type="singleton" />
          </type>
        </types>
      </container>
    </containers>
  </unity>

Domain Model

Nice, POCO classes, nothing relating to persistence or Entity Framework in here, just as it should be. All is right in the world;)

using System;
using System.Collections.Generic;

namespace KandaAlpha.Domain.Model.Entities
{
    public class Customer : EntityBase
    {
        public int CustomerID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string FullName
        {
            get
            {
                return FirstName + " " + LastName;
            }
        }
        public virtual List<Order> Orders {get; set;}
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace KandaAlpha.Domain.Model.Entities
{
    public class Order : EntityBase
    {
        public int OrderID { get; set; }
        public Customer Customer { get; set; }
        public decimal OrderTotal { get; set; }
    }
}

Domain Repository

So, IoC gives us an implementing class for ICustomerService which has a method GetRepository() which returns an ICustomerRepository implementation.

Leaving aside some of the wiring within the Application.Services component, let’s take a look a the ICustomerRepository interface defined within the Domain.Repository component

using System;
using KandaAlpha.Domain.Model.Entities;

namespace KandaAlpha.Domain.Repository
{
    public interface ICustomerRepository : IGenericRepository<Customer>
    {
        Customer GetBestCustomer();
    }
}

So, we have a single custom method on this repository, but most of the action is within the IGenericRepository<T>) class which defines our core repository behaviour as follows.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using KandaAlpha.Domain.Model.Entities;

namespace KandaAlpha.Domain.Repository
{
    public interface IGenericRepository<T> : IRepositoryBase where T : EntityBase
    {

        /// <summary>
        /// Return strongly typed IQueryable
        /// </summary>
        IQueryable<T> GetQuery();

        /// <summary>
        /// Load entity from the repository (always query store)
        /// </summary>
        /// <typeparam name="T">the entity type to load</typeparam>
        /// <param name="where">where condition</param>
        /// <returns>the loaded entity</returns>
        T Load(Expression<Func<T, bool>> whereCondition);

        /// <summary>
        /// Provides explicit loading of object properties
        /// </summary>
        void LoadProperty(T entity, Expression<Func<T, object>> selector);

        /// <summary>
        /// Returns all entities for a given type
        /// </summary>
        /// <returns>All entities</returns>
        List<T> GetAll();

        /// <summary>
        /// Add entity to the repository
        /// </summary>
        /// <param name="entity">the entity to add</param>
        /// <returns>The added entity</returns>
        void Add(T entity);

        /// <summary>
        /// Save all changes from repository to store
        /// </summary>
        /// <returns>Total number of objects affected</returns>
        int SaveChanges();

        /// <summary>
        /// Mark entity to be deleted within the repository
        /// </summary>
        /// <param name="entity">The entity to delete</param>
        void Delete(T entity);

    }
}

As you can see from the Unity IoC configuration ICustomerRepository is wired up to CustomerRepository within the Infrastructure.Repository.EF component. You can see hopefully how you could modify this to be NHibernate, ADO.Net or an in memory provider for quick testing if needs be by just changing the IoC configuration.

EF Repository Implementation

The core job of the EF Repository implementation is to then implement the ICustomerRepository and IGenericRepository<T> interfaces.

2009-05-30_2303[1]

The CustomerRepository and GenericRepository classes also make use of a static ObjectContextManager class. This implements a lifecycle management pattern across the EF’s object context which is one per http request (if HttpContext.Current is available) or one per thread for non web applications.

The EF’s edmx model class goes in this class library too. I followed the very simple instructions around how to enable POCO support for Entity Framework which largely entailed switching off code generation in the properties window of the edmx, nice!

Note the hand crafted KandaAlphaContext class which allows me to specify exactly what happens when the context gets created, including lazy loading options as follows:

 

public KandaAlphaContext() : base("name=KandaAlphaEntities", "KandaAlphaEntities")
{
    _customers = CreateObjectSet<Customer>();
    _orders = CreateObjectSet<Order>();
    base.ContextOptions.DeferredLoadingEnabled = true; // lazy loading
}

There is lastly an HttpRequestModule class which simply kills the object context at the end of each http request. For non web applications you would explicitly kill the context at the end of each unit of work. (although i haven’t yet got a facade method for that on the repository as yet).

Summary

I’m a big fan of the new Entity Framework. I think that the EF team are going to get this release spot on and we’ll see Entity Framework really establish itself as the ORM of choice for Microsoft developers. It will be interesting to see what the Alt.Net community make of EF v2 (sorry v4!), but from what i can see they’ve hit all the right buttons this time around. We’ll likely be talking about specific features, or sql optimisation as opposed to core architectural gripes this time around i feel.

As a big NHibernate fan too, I’m disappointed that Microsoft can’t co-opt more proven open source software like with JQuery as it’s a real boon to the .net community to have these projects flourish.

Saturday, May 30, 2009 11:31:16 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [12]  |  Trackback
Monday, June 08, 2009 7:24:52 AM (New Zealand Standard Time, UTC+12:00)
Thanks Keith - a really nice post!

In your implementation it is necessary to create a Service to create a Repository; can you tell us why?

I haven't referred back to Evans book but I don't remember this as being part of the pattern. From what I remember a Service would be used to provide business logic or functionality which doesn't naturally fit inside an entity (probably because the logic operates over more than one entity).

Perhaps some example of what else might be in your service rather than a single method to get the repository would be useful?

Thanks again for a great post,
Jason
Friday, June 12, 2009 7:27:31 PM (New Zealand Standard Time, UTC+12:00)
Hi Keith

Do you can, please, put a complete example using a generic repository and unit of work framework for CRUD operations with source code for download.

Thank!
Marcelo
Marcelo
Saturday, June 13, 2009 9:03:05 AM (New Zealand Standard Time, UTC+12:00)
This is a good example except of course for using WebForms and not injecting the service into your MVC Controller constructor.
All that's not included is the Visual Studio Project templates everything else will work with the workaround here.
http://haacked.com/archive/2009/05/18/aspnetmvc-vs2010-beta1.aspx
or you can get the new installer
http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=28527

However the POCO implementation in EF 2 falls apart when trying to Create or Update complex object graphs, what they are calling "Relationship Fix-up" means you need to write all the plumbing to do this and in the example from the ADO.NET blog they added a specific method to the Domain object called AddProduct to manage this. Would love to hear if you got an auto-magic solution to this.

Until this is resolved EFPocoAdapter is still the best solution for Persistance Ignorance with Entity Framework.
Wednesday, June 17, 2009 8:13:01 PM (New Zealand Standard Time, UTC+12:00)
hi will. will fix it up with mvc soon, now that it's released for vs.net 2010. Not sure how EFPocoAdapter deals with reconstruction of graphs which have left the bounds of an object context, why would the solution be any easier?
Wednesday, June 17, 2009 8:31:59 PM (New Zealand Standard Time, UTC+12:00)
httpJason,
The service layer is there to define orchestrations for the application utilising the domain. I agree it would have made more sense to provide alterative examples to highlight what this layer is for, but instead i'll refer you to the Service Layer definition here: http://www.martinfowler.com/eaaCatalog/serviceLayer.html

Workflow, calls to web services or file system (injected in infrastructure), transaction handling, exception handling, and other stateless application co-ordination would be what goes in here.

Hope that makes sense.

You don't have to have this layer. You could decide to inject repositories directly in your code behinds or controllers if using mvc, the choice is yours, but i like to have this layer, even if it remains relatively thin at times. ://blog.keithpatton.com/2009/05/30/Entity+Framework+POCO+Repository+Using+Visual+Studio+2010+Net+40+Beta+1.aspxz
Wednesday, June 17, 2009 8:36:35 PM (New Zealand Standard Time, UTC+12:00)
Will,

EF 2 supports "self tracking entities", http://blogs.msdn.com/adonet/archive/2009/05/14/sneak-preview-n-tier-development-with-entity-framework-4-0.aspx

this is not in the beta but should be coming in the next release. EF over n-tier should be significantly easier than v1 (thanks for reminding me;).

Sunday, June 21, 2009 7:26:06 AM (New Zealand Standard Time, UTC+12:00)
Self tracking entities sounds good, a little bit vague at the moment so will be interesting to see the impementation.
Really looking forward to doing away with all code that reattaches the entities to the ObjectContext.

Sorry the point I was making is that for Brownfield projects there is no compelling reason to upgrade to EF2 from EF1 and EFPocoAdapter as yet.
Friday, June 26, 2009 1:05:33 AM (New Zealand Standard Time, UTC+12:00)
Nice and helpful blog...
Wednesday, July 01, 2009 12:58:48 PM (New Zealand Standard Time, UTC+12:00)
Hi Keith,
Nice article on things I'm currently researching for a fairly major project where I work. I'm tasked with designing a new application server platform and application development framework to incrementally replace our 30 year old legacy app server. I've almost got an EF provider working with our proprietary RDBMS which is a necessary step regardless of how the app server turns out as we desperately need to expose our DB via an open .NET based O/RM in any case for a other reasons.

But I'm yet to see a convincing set of technologies that can replace the legacy application server to allow our developers to work more efficiently, as compared to their existing COBOL business logic and text screen development experience. Their current environment, while outdated, is surprisingly simple and efficient. There are other streams of development here spawning from necessity without much consideration into their future, such as an NHibernate based ASP.NET kiosk and a some custom ADO.NET applications but these are unlikely to scale well and don't offer a cohesive development platform or hosting environment.

I've come up with an architecture similar to what you propose in this article but it's not going to make life any easier for our application developers. On the contrary, they'll need to learn about principles like coding to contracts and interfaces, loose coupling, and end up writing a lot more code. I've looked at Microsoft's new RIA Services beta and it's definitely a step forwards to what we're aiming for. Do you think RIA Services and specifically a Silverlight 3 client could fit into your architecture? They seem to bolt directly onto the Entity Framework, ADO.NET Data Services and ADO.NET Dynamic Data not leaving much room for your repository or service layer.
Wednesday, July 01, 2009 12:59:32 PM (New Zealand Standard Time, UTC+12:00)
Also, can you clear this up for me. You state "Nice, POCO classes, nothing relating to persistence or Entity Framework in here, just as it should be. All is right in the world;)"
But in the example code you're deriving from 'EntityBase'
public class Customer : EntityBase

What is this EntityBase? I'm assuming it's not an EF class. Is it one of your classes? Is it there so that you can restrict GenericRepository<T> template specialisations with the conecpt 'where T : EntityBase' or does it provide other functionality?
Wednesday, July 15, 2009 4:42:09 PM (New Zealand Standard Time, UTC+12:00)
Keith, See you comment on Xero's blog. Good point on the single data centre. One thing, the captcha image doesn't display correct on Safari 4 (mac).
Wednesday, July 29, 2009 12:54:33 PM (New Zealand Standard Time, UTC+12:00)
I'm sure you know already, but you can download ASP.net MVC 1.1 for VS2010. It's really just 1.0, 2.0 will be in VS2010 Beta I hear.
Comments are closed.