Entity Framework 4 POCO, Repository and Specification Pattern

Updated (25 Aug 2010): There are some concerns from Jon and Buu about the performance hit when implementing the specification pattern follow the way that this post shows. That said, the implementation of this pattern has been updated and you can read it through at Specification Pattern In Entity Framework 4 Revisited
Updated: The post has a small update with the new release of Entity Framework Feature Community Technology Preview 4 (CTP4) in which the ObjectContextBuilder class changed its base class from ContextBuilder<T> to ModelBuilder. The source code has also been upgraded to CTP4 version. Note that to successfully compile the code, you have to install the EF CTP4 version which can be downloaded here.
After a decent period using NHibernate & SharpArchitecture to build .NET application, I eventually have a chance to work with Entity Framework (EF) in recent project. The client wants to leverage MS technologies as much as possible instead of some OSS frameworks to avoid learning curves and maintenance issues that might occurs later on. No matter what the decision is good or bad which some of you might agree or disagree, I am being put in a position to build the application with the team. And just because I have had some experience on building data access mechanism (mostly with ADO.NET and NHibernate), this more or less leads me to work with this data access layer again. 

Just like those who are going to work with a new technology, I started digging into EF by reading related books, hunting the web to find good articles and blog posts mentioning about building data access on top of EF. Since I have worked with NHibernate and also use Repository Pattern  to build the data access layer, the keywords entered Google should include: “Entity Framework”, “Entity Framework Repository”, “Entity Framework vs. NHibernate”, “Entity Framework POCO and Repository Pattern”  blah blah blah. Luckily I found quite a few of good posts (these will be listed as source of references at the end of this post).

With some sources of reference in hand, I started to build the data access layer using EF. But before talking about how I build it, here is a set of design patterns I want to apply: Repository, Unit of Work, and Specification. Since I also want to use POCOs instead of objects auto-generated by Visual Studio so this, once again, leads me to looking for the technique to write mapping stuff, and I found that it is also very easy.

Repository

Repository is defined as “an abstraction that provides us with persistence ignorance and a separation of concerns where the responsibility of persisting domain objects is encapsulated by the Repository that  leaving the domain objects to deal entirely with the domain model and domain logic.”

The contract for a repository contains operations to perform CRUD and also for querying entity objects.  The general technique is using .NET generic to build the Repository, the code below depicts the contract of repository:

public interface IRepository<TEntity> : IDisposable where TEntity : class
{
    IQueryable<TEntity> GetQuery();
    IEnumerable<TEntity> GetAll();
    IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate);
    TEntity Single(Expression<Func<TEntity, bool>> predicate);
    TEntity First(Expression<Func<TEntity, bool>> predicate);
    void Add(TEntity entity);
    void Delete(TEntity entity);
    void Attach(TEntity entity);
    void SaveChanges();
    void SaveChanges(SaveOptions options);
}

And the common implementation:

/// <summary>
/// A generic repository for working with data in the database
/// </summary>
/// <typeparam name="T">A POCO that represents an Entity Framework entity</typeparam>
public class GenericRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
    /// <summary>
    /// The context object for the database
    /// </summary>
    private ObjectContext _context;

    /// <summary>
    /// The IObjectSet that represents the current entity.
    /// </summary>
    private IObjectSet<TEntity> _objectSet;

    /// <summary>
    /// Initializes a new instance of the GenericRepository class
    /// </summary>
    /// <param name="context">The Entity Framework ObjectContext</param>
    public GenericRepository(ObjectContext context)
    {
        _context = context;
        _objectSet = _context.CreateObjectSet<TEntity>();
    }

    /// <summary>
    /// Gets all records as an IQueryable
    /// </summary>
    /// <returns>An IQueryable object containing the results of the query</returns>
    public IQueryable<TEntity> GetQuery()
    {
        return _objectSet;
    }

    /// <summary>
    /// Gets all records as an IEnumberable
    /// </summary>
    /// <returns>An IEnumberable object containing the results of the query</returns>
    public IEnumerable<TEntity> GetAll()
    {
        return GetQuery().AsEnumerable();
    }

    /// <summary>
    /// Finds a record with the specified criteria
    /// </summary>
    /// <param name="predicate">Criteria to match on</param>
    /// <returns>A collection containing the results of the query</returns>
    public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
    {
        return _objectSet.Where<TEntity>(predicate);
    }

    /// <summary>
    /// Gets a single record by the specified criteria (usually the unique identifier)
    /// </summary>
    /// <param name="predicate">Criteria to match on</param>
    /// <returns>A single record that matches the specified criteria</returns>
    public TEntity Single(Expression<Func<TEntity, bool>> predicate)
    {
        return _objectSet.Single<TEntity>(predicate);
    }

    /// <summary>
    /// The first record matching the specified criteria
    /// </summary>
    /// <param name="predicate">Criteria to match on</param>
    /// <returns>A single record containing the first record matching the specified criteria</returns>
    public TEntity First(Expression<Func<TEntity, bool>> predicate)
    {
        return _objectSet.First<TEntity>(predicate);
    }

    /// <summary>
    /// Deletes the specified entitiy
    /// </summary>
    /// <param name="entity">Entity to delete</param>
    /// <exception cref="ArgumentNullException"> if <paramref name="entity"/> is null</exception>
    public void Delete(TEntity entity)
    {
        if (entity == null)
        {
            throw new ArgumentNullException("entity");
        }

        _objectSet.DeleteObject(entity);
    }

    /// <summary>
    /// Adds the specified entity
    /// </summary>
    /// <param name="entity">Entity to add</param>
    /// <exception cref="ArgumentNullException"> if <paramref name="entity"/> is null</exception>
    public void Add(TEntity entity)
    {
        if (entity == null)
        {
            throw new ArgumentNullException("entity");
        }

        _objectSet.AddObject(entity);
    }

    /// <summary>
    /// Attaches the specified entity
    /// </summary>
    /// <param name="entity">Entity to attach</param>
    public void Attach(TEntity entity)
    {
        _objectSet.Attach(entity);
    }

    /// <summary>
    /// Saves all context changes
    /// </summary>
    public void SaveChanges()
    {
        _context.SaveChanges();
    }

    /// <summary>
    /// Saves all context changes with the specified SaveOptions
    /// </summary>
    /// <param name="options">Options for saving the context</param>
    public void SaveChanges(SaveOptions options)
    {
        _context.SaveChanges(options);
    }

    /// <summary>
    /// Releases all resources used by the WarrantManagement.DataExtract.Dal.ReportDataBase
    /// </summary>
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    /// <summary>
    /// Releases all resources used by the WarrantManagement.DataExtract.Dal.ReportDataBase
    /// </summary>
    /// <param name="disposing">A boolean value indicating whether or not to dispose managed resources</param>
    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (_context != null)
            {
                _context.Dispose();
                _context = null;
            }
        }
    }
}

As you can see, the repository use a generic type of TEntity to represent an entity that we want to manipulate. Suppose we have an entity named Customer, when we need to perform operations on Customer entity we will do something like this:

IRepository<Customer> customerRepository = new GenericRepository<Customer>();

// Gets all customers
IEnumerable<Customer> customers = customerRepository.GetAll();

// Insert a new customer
Customer customer = new Customer { Firstname = "Huy", Lastname = "Nguyen" };
customerRepository.Add(customer);
customerRepository.SaveChanges();

For some specific entity selection, instead of widening the contract of generic repository, the common technique is to subclass the generic repository to implement a specific repository:

public class CustomerRepository : GenericRepository<Customer>, ICustomerRepository
{
    public CustomerRepository(ObjectContext context) : base(context) { }

    public IList<Customer> NewlySubscribed()
    {
        var lastMonth = DateTime.Now.Date.AddMonths(-1);

        return GetQuery().Where(c => c.Inserted >= lastMonth)
        .ToList();
    }

    public Customer FindByName(string firstname, string lastname)
    {
        return GetQuery().Where(c => c.Firstname == firstname && c.Lastname == lastname).FirstOrDefault();
    }
}

But I find it a bit inconvenient since we have to create multiple repository instances in case we want to work with multiple entities at a time. In other words, if we want to perform operations on n entities, we have to create nearly n repository instances (I am saying ‘nearly’ because if an entity is not an aggregate root, we do not implement a repository for it), like the code below:

private void AddOrders()
{
    var context = new NorthwindEntities("connectionString");

    var customerRepository = new CustomerRepository(context);
    IRepository<Order> orderRepository = new GenericRepository<Order>(context);
    IRepository<Product> productRepository = new GenericRepository<Product>(context);

    var c = customerRepository.FindByName("John", "Doe");

    var winXP = productRepository.Single(x => x.Name == "Windows XP Professional");
    var winSeven = productRepository.Single(x => x.Name == "Windows Seven Professional");

    var o = new Order
    {
        OrderDate = DateTime.Now,
        Purchaser = c,
        OrderLines = new List<OrderLine>
        {
            new OrderLine { Price = 200, Product = winXP, Quantity = 1},
            new OrderLine { Price = 699.99, Product = winSeven, Quantity = 5 }
        }
    };

    orderRepository.Add(o);
    orderRepository.SaveChanges();
}

To get rid of that inconvenient, I decide to re-implement the more generic repository by making the repository’s methods generic:

public interface IRepository : IDisposable
{
    IQueryable<TEntity> GetQuery<TEntity>() where TEntity : class;
    IEnumerable<TEntity> GetAll<TEntity>() where TEntity : class;
    IEnumerable<TEntity> Find<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : class;
    TEntity Single<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : class;
    TEntity First<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : class;
    void Add<TEntity>(TEntity entity) where TEntity : class;
    void Delete<TEntity>(TEntity entity) where TEntity : class;
    void Attach<TEntity>(TEntity entity) where TEntity : class;
    void SaveChanges();
    void SaveChanges(SaveOptions options);
}
And here is the implementation for the revised repository contract:
/// <summary>
/// A generic repository for working with data in the database
/// </summary>
/// <typeparam name="T">A POCO that represents an Entity Framework entity</typeparam>
public class GenericRepository : IRepository
{
    /// <summary>
    /// The context object for the database
    /// </summary>
    private ObjectContext _context;
    private readonly PluralizationService _pluralizer;

    /// <summary>
    /// Initializes a new instance of the GenericRepository class
    /// </summary>
    /// <param name="context">The Entity Framework ObjectContext</param>
    public GenericRepository(ObjectContext context)
    {
        _context = context;
        _pluralizer = PluralizationService.CreateService(CultureInfo.GetCultureInfo("en"));
    }

    public IQueryable<TEntity> GetQuery<TEntity>() where TEntity : class
    {
        var entityName = GetEntityName<TEntity>();
        return _context.CreateQuery<TEntity>(entityName);
    }

    public IEnumerable<TEntity> GetAll<TEntity>() where TEntity : class
    {
        return GetQuery<TEntity>().AsEnumerable();
    }

    public IEnumerable<TEntity> Find<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : class
    {
        return GetQuery<TEntity>().Where(predicate).AsEnumerable();
    }

    public TEntity Single<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : class
    {
        return GetQuery>TEntity>().Single<TEntity>(predicate);
    }

    public TEntity First<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : class
    {
        return GetQuery<TEntity>().Where(predicate).FirstOrDefault();
    }

    public void Add<TEntity>(TEntity entity) where TEntity : class
    {
        _context.AddObject(GetEntityName<TEntity>(), entity);
    }

    public void Delete<TEntity>(TEntity entity) where TEntity : class
    {
        _context.DeleteObject(entity);
    }

    private string GetEntityName<TEntity>() where TEntity : class
    {
        return string.Format("ObjectContext.{0}", _pluralizer.Pluralize(typeof(TEntity).Name));
    }
    // ...
}
With this repository we can now create only one repository every time we need to retrieve or persist an entity, we can even make this repository an instance member to be retrieved across class methods. Here is the new AddOrders method using this new repository:
private void AddOrders()
{
    var context = new NorthwindEntities("connectionString");

    var customerRepository = new CustomerRepository(context);
    var repository = new GenericRepository(context);

    var c = customerRepository.FindByName("John", "Doe");

    var winXP = repository.Single<Product>(x => x.Name == "Windows XP Professional");
    var winSeven = repository.Single<Product>(x => x.Name == "Windows Seven Professional");

    var o = new Order
    {
        OrderDate = DateTime.Now,
        Purchaser = c,
        OrderLines = new List<OrderLine>
        {
            new OrderLine { Price = 200, Product = winXP, Quantity = 1},
            new OrderLine { Price = 699.99, Product = winSeven, Quantity = 5 }
        }
    };

    repository.Add<Order>(o);
    repository.SaveChanges();
}
Of course one also creates the specific repository to widen the contract using inheritence (like CustomerRepository above) or narrow it using adapter if she wants to.
Unit of Work
The EF ObjectContext does this work for us in regarding managing UnitOfWork. It is already able to handle transaction across many operations over many different types. All we have to do is to call SaveChanges method on the ObjectContext instance as described in the above test code.
With the current implementation so far, we now have a handy generic repository to be used for data persistence and transaction handling. But there is a slight issue with this implementation. The problem being, if I had multiple POCO objects, for instance, Repository<Customer> and Repository<Product>, we would not able to run queries across both, as they would be created via different instances of ObjectContext and this leads to losing any level 1 caching.
A common solution is to build a object context factory. Every time we need an object context instance, just delegate this work to this factory class. Here is a possible implementation:
public static class ObjectContextFactory
{
    /// <summary>
    /// Gets the default ObjectContext for the project
    /// </summary>
    /// <returns>The default ObjectContext for the project</returns>
    public static NorthwindEntities GetContext()
    {
        string connectionString = ConfigurationManager.ConnectionStrings["YourConnection"].ConnectionString;

        return GetContext(connectionString);
    }

    /// <summary>
    /// Gets the default ObjectContext for the project
    /// </summary>
    /// <param name="connectionString">Connection string to use for database queries</param>
    /// <returns>The default ObjectContext for the project</returns>
    public static NorthwindEntities GetContext(string connectionString)
    {
        return new NorthwindEntities(connectionString);
    }
}
To use it, just simply do something like the following:
private void AddOrders()
{
    var context = ObjectContextFactory.GetContext("connectionString");

    var customerRepository = new CustomerRepository(context);
    var repository = new GenericRepository(context);

    var c = customerRepository.FindByName("John", "Doe");

    var winXP = repository.Single<Product>(x => x.Name == "Windows XP Professional");
    var winSeven = repository.Single<Product>(x => x.Name == "Windows Seven Professional");

    var o = new Order
    {
        OrderDate = DateTime.Now,
        Purchaser = c,
        OrderLines = new List<OrderLine>
        {
            new OrderLine { Price = 200, Product = winXP, Quantity = 1},
            new OrderLine { Price = 699.99, Product = winSeven, Quantity = 5 }
        }
    };

    repository.Add<Order>(o);
    repository.SaveChanges();
}
At this time, I again find another inconvenient way to manage the object context. Look at the code above you will easily find that every time we work with another type of object context in another application, we have to rewrite the factory in order for it to return the actual type we need instead of the example NorthwindEntities. Is there a way to make this factory class unchanged so that we can reuse it in every application that works with any concrete instance of object context?
This reminds me about the NHibernate session manager implemented in SharpArchitecture code base. So I decide to write an object context manager which acts like that session manager. Its responsibility is to provide a mechanism to create context on demand, and it also provides a storage mechanism which is context-dependent (http context, wcf, and so on) to store object context.
public static class ObjectContextManager
{
    public static void Init(string[] mappingAssemblies, bool recreateDatabaseIfExist = false)
    {
        Init(DefaultConnectionStringName, mappingAssemblies, recreateDatabaseIfExist);
    }

    public static void Init(string connectionStringName, string[] mappingAssemblies, bool recreateDatabaseIfExist = false)
    {
        AddConfiguration(connectionStringName, mappingAssemblies, recreateDatabaseIfExist);
    }

    public static void InitStorage(IObjectContextStorage storage)
    {
        if (storage == null)
        {
            throw new ArgumentNullException("storage");
        }
        if ((Storage != null) && (Storage != storage))
        {
            throw new ApplicationException("A storage mechanism has already been configured for this application");
        }
        Storage = storage;
    }

    /// <summary>
    /// The default connection string name used if only one database is being communicated with.
    /// </summary>
    public static readonly string DefaultConnectionStringName = "DefaultDb";

    /// <summary>
    /// Used to get the current object context session if you're communicating with a single database.
    /// When communicating with multiple databases, invoke <see cref="CurrentFor()" /> instead.
    /// </summary>
    public static ObjectContext Current
    {
        get
        {
            return CurrentFor(DefaultConnectionStringName);
        }
    }

    /// <summary>
    /// Used to get the current ObjectContext associated with a key; i.e., the key
    /// associated with an object context for a specific database.
    ///
    /// If you're only communicating with one database, you should call <see cref="Current" /> instead,
    /// although you're certainly welcome to call this if you have the key available.
    /// </summary>
    public static ObjectContext CurrentFor(string key)
    {
        if (string.IsNullOrEmpty(key))
        {
            throw new ArgumentNullException("key");
        }

        if (Storage == null)
        {
            throw new ApplicationException("An IObjectContextStorage has not been initialized");
        }

        if (!objectContextBuilders.ContainsKey(key))
        {
            throw new ApplicationException("An ObjectContextBuilder does not exist with a key of " + key);
        }

        ObjectContext context = Storage.GetObjectContextForKey(key);

        if (context == null)
        {
            context = objectContextBuilders[key].BuildObjectContext();
            Storage.SetObjectContextForKey(key, context);
        }

        return context;
    }

    /// <summary>
    /// This method is used by application-specific object context storage implementations
    /// and unit tests. Its job is to walk thru existing cached object context(s) and Close() each one.
    /// </summary>
    public static void CloseAllObjectContexts()
    {
        foreach (ObjectContext ctx in Storage.GetAllObjectContexts())
        {
            if (ctx.Connection.State == System.Data.ConnectionState.Open)
                ctx.Connection.Close();
        }
    }

    private static void AddConfiguration(string connectionStringName, string[] mappingAssemblies, bool recreateDatabaseIfExists = false)
    {
        if (string.IsNullOrEmpty(connectionStringName))
        {
            throw new ArgumentNullException("connectionStringName");
        }

        if (mappingAssemblies == null)
        {
            throw new ArgumentNullException("mappingAssemblies");
        }

        objectContextBuilders.Add(connectionStringName,
            new ObjectContextBuilder<ObjectContext>(connectionStringName, mappingAssemblies, recreateDatabaseIfExists));
    }

    /// <summary>
    /// An application-specific implementation of IObjectContextStorage must be setup either thru
    /// <see cref="InitStorage" /> or one of the <see cref="Init" /> overloads.
    /// </summary>
    private static IObjectContextStorage Storage { get; set; }

    /// <summary>
    /// Maintains a dictionary of object context builders, one per database.  The key is a
    /// connection string name used to look up the associated database, and used to decorate respective
    /// repositories. If only one database is being used, this dictionary contains a single
    /// factory with a key of <see cref="DefaultConnectionStringName" />.
    /// </summary>
    private static Dictionary<string, IObjectContextBuilder<ObjectContext>> objectContextBuilders =
        new Dictionary<string, IObjectContextBuilder<ObjectContext>>();
}
As you can see, ObjectContextManager delegates the job to create an object context to a so-called ObjectContextBuilder class. The main responsibility of this class  is to create an object context using the provided connection string and also to look up and configure the entity mapping classes. This class constructor accepts a connection string name and an array of mapping assemblies, which contain entity definitions and mapping classes, for it to create an object context (these two parameters was provided during application starting up by calling method ObjectContextManager.Init(…)). If you have ever used SharpArchitecture code, you can see it is almost the same as NHibernate’s SessionFactory class.
Here is the code of ObjectContextBuilder class:
public interface IObjectContextBuilder<T> where T : ObjectContext
{
    T BuildObjectContext(bool lazyLoadingEnabled = true);
}

public class ObjectContextBuilder<T> : ContextBuilder<T>, IObjectContextBuilder<T> where T : ObjectContext
{
    private readonly DbProviderFactory _factory;
    private readonly ConnectionStringSettings _cnStringSettings;
    private readonly PluralizationService _pluralizer;
    private readonly bool _recreateDatabaseIfExists;

    public ObjectContextBuilder(string connectionStringName, string[] mappingAssemblies, bool recreateDatabaseIfExists)
    {
        _cnStringSettings = ConfigurationManager.ConnectionStrings[connectionStringName];
        _factory = DbProviderFactories.GetFactory(_cnStringSettings.ProviderName);
        _pluralizer = PluralizationService.CreateService(CultureInfo.GetCultureInfo("en"));
        _recreateDatabaseIfExists = recreateDatabaseIfExists;

        AddConfigurations(mappingAssemblies);
    }

    /// <summary>
    /// Creates a new <see cref="ObjectContext"/>.
    /// </summary>
    /// <param name="lazyLoadingEnabled">if set to <c>true</c> [lazy loading enabled].</param>
    /// <param name="recreateDatabaseIfExist">if set to <c>true</c> [recreate database if exist].</param>
    /// <returns></returns>
    public T BuildObjectContext(bool lazyLoadingEnabled = true)
    {
        var cn = _factory.CreateConnection();
        cn.ConnectionString = _cnStringSettings.ConnectionString;

        var ctx = Create(cn);
        ctx.ContextOptions.LazyLoadingEnabled = lazyLoadingEnabled;

        if (!ctx.DatabaseExists())
        {
            ctx.CreateDatabase();
        }
        else if (_recreateDatabaseIfExists)
        {
            ctx.DeleteDatabase();
            ctx.CreateDatabase();
        }

        return ctx;
    }

    /// <summary>
    /// Adds mapping classes contained in provided assemblies and register entities as well
    /// </summary>
    /// <param name="mappingAssemblies"></param>
    private void AddConfigurations(string[] mappingAssemblies)
    {
        if (mappingAssemblies == null || mappingAssemblies.Length == 0)
        {
            throw new ArgumentNullException("mappingAssemblies", "You must specify at least one mapping assembly");
        }

        foreach (string mappingAssembly in mappingAssemblies)
        {
            Assembly asm = Assembly.LoadFrom(MakeLoadReadyAssemblyName(mappingAssembly));

            foreach (Type type in asm.GetTypes())
            {
                if (!type.IsAbstract)
                {
                    if (type.IsSubclassOf(typeof(StructuralTypeConfiguration)))
                    {
                        StructuralTypeConfiguration instance = Activator.CreateInstance(type) as StructuralTypeConfiguration;
                        this.Configurations.Add(instance);

                        Type entityType = GetEntityType(type);
                        if (entityType != null)
                        {
                            RegisterEntity(entityType);
                        }
                    }
                }
            }
        }

        if (this.Configurations.Count == 0)
        {
            throw new ArgumentException("No mapping class found!");
        }
    }
    // other code
}
Updated: ADO.NET team just announced the release of Entity Framework Feature  Community Technology Preview 4 (CTP4) which splits ContextBuilder into two components, ModelBuilder and DbModel. The definition of the two new classes are as “ModelBuilder is mutable and exposes the fluent API for defining your model. ModelBuilder creates an immutable DbModel type that can be used to construct an ObjectContext or DbContext. DbModel can also be constructed from a Database First or Model First approach where an edmx file is generated.” Here is the updated ObjectContextBuilder class which replaces the inheritance from ContextBuilder to ModelBuilder class. Note that to make the code compilable, you must install the EF CTP4 version
public interface IObjectContextBuilder<T> where T : ObjectContext
{
    T BuildObjectContext(bool lazyLoadingEnabled = true);
}

public class ObjectContextBuilder<T> : ModelBuilder, IObjectContextBuilder<T> where T : ObjectContext
{
    private readonly DbProviderFactory _factory;
    private readonly ConnectionStringSettings _cnStringSettings;
    private readonly PluralizationService _pluralizer;
    private readonly bool _recreateDatabaseIfExists;

    public ObjectContextBuilder(string connectionStringName, string[] mappingAssemblies, bool recreateDatabaseIfExists)
    {
        _cnStringSettings = ConfigurationManager.ConnectionStrings[connectionStringName];
        _factory = DbProviderFactories.GetFactory(_cnStringSettings.ProviderName);
        _pluralizer = PluralizationService.CreateService(CultureInfo.GetCultureInfo("en"));
        _recreateDatabaseIfExists = recreateDatabaseIfExists;

        // we do not want the EdmMedadata table to be generated
        IncludeMetadataInDatabase = false;

        AddConfigurations(mappingAssemblies);
    }

    /// <summary>
    /// Creates a new <see cref="ObjectContext"/>.
    /// </summary>
    /// <param name="lazyLoadingEnabled">if set to <c>true</c> [lazy loading enabled].</param>
    /// <param name="recreateDatabaseIfExist">if set to <c>true</c> [recreate database if exist].</param>
    /// <returns></returns>
    public T BuildObjectContext(bool lazyLoadingEnabled = true)
    {
        var cn = _factory.CreateConnection();
        cn.ConnectionString = _cnStringSettings.ConnectionString;

        // calls ModelBuilder.CreateModel() to create DbModel, then uses it to create ObjectContext
        var ctx = CreateModel().CreateObjectContext<T>(cn);
        ctx.ContextOptions.LazyLoadingEnabled = lazyLoadingEnabled;

        if (!ctx.DatabaseExists())
        {
            ctx.CreateDatabase();
        }
        else if (_recreateDatabaseIfExists)
        {
            ctx.DeleteDatabase();
            ctx.CreateDatabase();
        }

        return ctx;
    }
    // other code are kept the same
}
With this ObjectContextManager in hand, I re-factor the Repository class by removing the dependency to ObjectContext in its constructor, every time it needs a ObjectContext, it will ask the ObjectContextManager to provide.
/// <summary>
/// Generic repository
/// </summary>
public class GenericRepository : IRepository
{
    private readonly ObjectContext _context;
    private readonly PluralizationService _pluralizer;

    /// <summary>
    /// Initializes a new instance of the <see cref="Repository&lt;TEntity&gt;"/> class.
    /// </summary>
    public GenericRepository()
        : this(string.Empty)
    {
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="Repository&lt;TEntity&gt;"/> class.
    /// </summary>
    /// <param name="connectionStringName">Name of the connection string.</param>
    public GenericRepository(string connectionStringName)
    {
        _context = GetObjectContext(connectionStringName);
        _pluralizer = PluralizationService.CreateService(CultureInfo.GetCultureInfo("en"));
    }

    private ObjectContext GetObjectContext(string connectionStringName)
    {
        if (connectionStringName == string.Empty)
            return ObjectContextManager.Current;
        return ObjectContextManager.CurrentFor(connectionStringName);
    }
    // other code
}

So far so good, here is the revisited test code:

[TestFixture]
public class RepositoryTest
{
    private ICustomerRepository customerRepository;
    private IRepository orderRepository;
    private IRepository productRepository;

    [TestFixtureSetUp]
    public void SetUp()
    {
        ObjectContextManager.InitStorage(new SimpleObjectContextStorage());
        ObjectContextManager.Init("DefaultDb", new[] { "Infrastructure.Tests" }, true);

        customerRepository = new CustomerRepository();
        orderRepository = new GenericRepository();
        productRepository = new GenericRepository();
    }

    private void AddOrders()
    {
        var c = customerRepository.FindByName("John", "Doe");

        var winXP = productRepository.FindOne<Product>(x => x.Name == "Windows XP Professional");
        var winSeven = productRepository.FindOne<Product>(x => x.Name == "Windows Seven Professional");

        var o = new Order
        {
            OrderDate = DateTime.Now,
            Purchaser = c,
            OrderLines = new List<OrderLine>
            {
                new OrderLine { Price = 200, Product = winXP, Quantity = 1},
                new OrderLine { Price = 699.99, Product = winSeven, Quantity = 5 }
            }
        };

        orderRepository.Add(o);
        orderRepository.SaveChanges();
    }
}
The Specification pattern
According to Martin Flowler, the idea of Specification is to separate the statement of how to match a candidate, from the candidate object that it is matched against. As well as its usefulness in selection, it is also valuable for validation and for building to order. You can also follow the Specification white paper by Martin Flowler if you want to indulge yourself deeply into this programming pattern.
In simple terms, it is a small piece of logic which is independent and give an answer to the question “does this match ?”. With Specification, we isolate the logic that do the selection into a reusable business component that can be passed around easily from the entity we are selecting.
Okay, it is enough for introducing specification pattern. Here is the specification contract:
public interface ISpecification<TEntity>
{
    bool IsSatisfiedBy(TEntity entity);
}
And the extended repository contract:
public interface IRepository
{
    // other methods..
    TEntity Single<TEntity>(ISpecification<TEntity> criteria) where TEntity : class

    IEnumerable<TEntity> Find<TEntity>(ISpecification<TEntity> criteria) where TEntity : class
}
Now is the implementation of the extended repository:
public class GenericRepository : IRepository
{
    // other code...
    public TEntity Single<TEntity>(ISpecification<TEntity> criteria) where TEntity : class
    {
        return GetQuery<TEntity>().Single<TEntity>(criteria.IsSatisfiedBy);
    }

    public IEnumerable<TEntity> Find<TEntity>(ISpecification<TEntity> criteria) where TEntity : class
    {
        return GetQuery<TEntity>().Where(criteria.IsSatisfiedBy).AsEnumerable();
    }
    // other code...
}
Some of the sample specification implementation:
public class Specification<TEntity> : ISpecification<TEntity>
{
    public Specification(Expression<Func<TEntity, bool>> predicate)
    {
        _predicate = predicate;
    }

    public bool IsSatisfiedBy(TEntity entity)
    {
        return _predicate.Compile().Invoke(entity);
    }

    private Expression<Func<TEntity, bool>> _predicate;
}

public class ProductByNameSpecification : Specification<Product>
{
    public ProductByNameSpecification(string nameToMatch)
        : base(p => p.Name == nameToMatch)
    {
    }
}

public class ProductOnSaleSpecification : Specification<Product>
{
    public ProductOnSaleSpecification() : base(p => p.Price < 100) { }
}
At this point, I think of a technique to chain the specification called composite specification. Why not apply to make the specification flexible and reusable? Here is the code which is mostly inspired from this post:
public class Specification<TEntity> : ISpecification<TEntity>
{
    public Specification(Expression<Func<TEntity, bool>> predicate)
    {
        _predicate = predicate;
    }

    public AndSpecification<TEntity> And(Specification<TEntity> specification)
    {
        return new AndSpecification<TEntity>(this, specification);
    }

    public OrSpecification<TEntity> Or(Specification<TEntity> specification)
    {
        return new OrSpecification<TEntity>(this, specification);
    }

    public NotSpecification<TEntity> Not(Specification<TEntity> specification)
    {
        return new NotSpecification<TEntity>(this, specification);
    }

    public bool IsSatisfiedBy(TEntity entity)
    {
        return _predicate.Compile().Invoke(entity);
    }

    private Expression<Func<TEntity, bool>> _predicate;
}

/// <summary>
/// http://devlicio.us/blogs/jeff_perrin/archive/2006/12/13/the-specification-pattern.aspx
/// </summary>
/// <typeparam name="TEntity"></typeparam>
public abstract class CompositeSpecification<TEntity> : ISpecification<TEntity>
{
    protected readonly Specification<TEntity> _leftSide;
    protected readonly Specification<TEntity> _rightSide;

    public CompositeSpecification(Specification<TEntity> leftSide, Specification<TEntity> rightSide)
    {
        _leftSide = leftSide;
        _rightSide = rightSide;
    }

    public abstract bool IsSatisfiedBy(TEntity entity);
}

public class AndSpecification<TEntity> : CompositeSpecification<TEntity>
{
    public AndSpecification(Specification<TEntity> leftSide, Specification<TEntity> rightSide)
        : base(leftSide, rightSide)
    {
    }

    public override bool IsSatisfiedBy(TEntity obj)
    {
        return _leftSide.IsSatisfiedBy(obj) && _rightSide.IsSatisfiedBy(obj);
    }
}

public class OrSpecification<TEntity> : CompositeSpecification<TEntity>
{
    public OrSpecification(Specification<TEntity> leftSide, Specification<TEntity> rightSide)
        : base(leftSide, rightSide)
    {
    }

    public override bool IsSatisfiedBy(TEntity entity)
    {
        return _leftSide.IsSatisfiedBy(entity) || _rightSide.IsSatisfiedBy(entity);
    }
}

public class NotSpecification<TEntity> : CompositeSpecification<TEntity>
{
    public NotSpecification(Specification<TEntity> leftSide, Specification<TEntity> rightSide)
        : base(leftSide, rightSide)
    {
    }

    public override bool IsSatisfiedBy(TEntity entity)
    {
        return _leftSide.IsSatisfiedBy(entity) && !_rightSide.IsSatisfiedBy(entity);
    }
}
And here is the code to test the composite specification
[TestFixture]
public class RepositoryTest
{
    private ICustomerRepository customerRepository;
    private IRepository orderRepository;
    private IRepository productRepository;

    [TestFixtureSetUp]
    public void SetUp()
    {
        ObjectContextManager.InitStorage(new SimpleObjectContextStorage());
        ObjectContextManager.Init("DefaultDb", new[] { "Infrastructure.Tests" }, true);
        customerRepository = new CustomerRepository();
        orderRepository = new GenericRepository();
        productRepository = new GenericRepository();
    }

    [Test]
    public void Test()
    {
        // setup data code..

        FindBySpecification();
        FindByCompositeSpecification();
        FindByConcretSpecification();
        FindByConcretCompositeSpecification();
    }
    private void FindBySpecification()
    {
        Specification<Product> specification = new Specification<Product>(p => p.Price < 100);
        IEnumerable<Product> productsOnSale = productRepository.Find<Product>(specification);
        Assert.AreEqual(2, productsOnSale.Count());
    }

    private void FindByCompositeSpecification()
    {
        IEnumerable<Product> products = productRepository.Find<Product>(
        new Specification<Product>(p => p.Price < 100).And(new Specification<Product>(p => p.Name == "Windows XP Professional")));
        Assert.AreEqual(1, products.Count());
    }

    private void FindByConcretSpecification()
    {
        ProductOnSaleSpecification specification = new ProductOnSaleSpecification();
        IEnumerable<Product> productsOnSale = productRepository.Find<Product>(specification);
        Assert.AreEqual(2, productsOnSale.Count());
    }

    private void FindByConcretCompositeSpecification()
    {
        IEnumerable<Product> products = productRepository.Find<Product>(
        new AndSpecification<Product>(
        new ProductOnSaleSpecification(),
        new ProductByNameSpecification("Windows XP Professional")));
        Assert.AreEqual(1, products.Count());
    }
}
Conclusion
That’s it. I hope you find something useful with the of generic repository, the way to manage object context, and the composite specification implementation as well. Comments are welcome!
References

The code for this post can be found here.

About these ads

Posted on July 13, 2010, in design, Programming and tagged , , , . Bookmark the permalink. 117 Comments.

  1. Awesome!! I really like how you did not put the generic constraint on the class level! Makes it so much more useful. I have not used Entity Framework for a long time since I prefer the Fluent NHibernate way of mapping tables to classes. The usage of the ObjectContext also becomes sort of atomic which is really good since it is not thread safe.

    Good work!!

  2. This post is very interested in. I like your implementation on the Repository and Specification patterns. In the source code on google, you implemented code-first for this project. It’s so cool. As far as I knew, code first on EF4 is “can’t call store-procedure”. Do you have any methods for invoking store-procedure?

  3. @Mikael: glad you find it interesting :)

    @thangchung: currently I don’t since it is just a prototype to demonstrate how to EF POCO and other things. But I think it is very easy to support calling stored-procedure by extend the repository contract.

  4. If i were you, I will remove the method Attach/SaveChanges from the IRepository to IUnitofWorkRepository and make this new interface inherit from the old one. I like the way you use ObjectContextFactory, however I prefer using a IOC library than building these classes. It’s very nice work. I believe It took you at least 3 days to compose this entry, including screen shot making and layout customization :D

  5. @Thoai: Nice comment. And yes, you can use IoC or whatever you want for injecting UnitOfWork as long as you are comfortable with using it. I just wanted to keep the prototype simple and easy to understand. I believe there are many points to extend the repository contract to meet the real needs but I just want to leave it to reader(s). When they deeply understand the idea, they can make improvement on it.

    You are right that the post took me days to complete. I don’t really like using screenshot for code example but it’s a shame that I don’t know how to format text code in order for it to be easy to read as in Visual Studio, so it was the only choice :))

  6. @aHuy: You can use http://code.google.com/p/syntaxhighlighter for formatting code, or if you use VS2010, you can install extension with name Pro Power Tool, so you can paste all code from VS editor to rich editor on web (all code shall auto convert to html). IMHO

  7. Very nice code! ObjectContextManager doesn’t seem to be thread-safe. I suppose it’s intentional.

  8. @Buu: Thanks for your comment. If you look at the code download, you will see there is an ObjectContextInitializer (singleton) class which is use to initialize object context in a thread safe manner.

  9. Ah, right, the ObjectContextManager is thread safe at initializing ObjectContext but not its CurrentFor method. I think making it thread safety is trivial for you guys :)

  10. Yes, I meant CurrentFor :). Minor catch, have nothing to do with the super quality of your code.

  11. Nice code a.Hung. I learnt some things from your code.

  12. @Bao: good to know >”<

  13. This is simply amazing, my eyes are burning with glee. I am fascinated by the effort that you have put in creating this. I can simply use this in my projects.

  14. This is a very informative post… An excellent example of Composite Specification Pattern. This is a really good head start for someone who wants implement data access layer using EF4 POCO.

  15. Thanks for the great solution of DDD!

  16. Hello,

    The code looks very good. My main concern with it is that the generic repository class is tied to the entity framework by the ObjectContext dependency.

    That complicates using the repository for testing since all tests would hit the database.

    The typical solution would be to create an IObjectContext interface for instance that the model context implements and then replace the ObjectContext dependency with that interface.

    However, for larger applications with multiple data models, each model has a different context (that likely implement unique interfaces) and it becomes more complicated for the generic repository to be usable for each of those models without duplicating the generic repository for each model.

    Please let me know if you can think of a good solution to allow the generic repository to be re-used for multiple models within a single application from a testing scenario when each model may need to implement a unique interface.

    Thanks,

    Anthony

    • Thanks for comment, Anthony.

      You’re right, the code is tightly coupled to EF via ObjectContent dependency. But it’s fine, at least to me. The reason is when I need to test the repository, I accept that test hits the database because I need to make sure it generates correct database tables and their relationships. That proves the mapping code was correctly written. On the other hand, when I test a service class which has dependency to the repository, I simply mock the repository. This keeps the test for that service from hitting the database.

      Regarding the multiple data models, my understanding is that you want to connect to multiple databases? If yes, then I think the code already supports your need. What you need to do is using ObjectContextInitializer to initialize all the models at application start up, assign each with a specific connection string name, then every time you want to use the repository to access a database (model), just instantiate it like this:

      GenericRepository repository = new GenericRepository(“connection string name””);

      // connection string name is the name which is associated with a database (model) that you has initialized using ObjectContextInitializer.

      Hope this make sense to you.

  17. Hello Huy,

    Thanks for your reply. I figured you were likely testing against the database and we’ve considered that as well, at least against a test database. But we are generating the model from the database so we are more certain about relationships and such.

    Still, when you mock the repository, isn’t the dependency on the ObjectContext still there since it is a parameter in one of your constructor overloads?

    Regarding multiple models, EF4 still doesn’t perform well with large models so the typical solution is to break large models into smaller modesl even against the same database.

    Here are a few articles regarding the large model issue in case you are interested:

    http://blogs.msdn.com/b/adonet/archive/2008/11/24/working-with-large-models-in-entity-framework-part-1.aspx

    http://thedatafarm.com/blog/data-access/creating-models-from-databases-with-billions-of-tables/

    Thanks again,

    Anthony

    • Anthony,

      When I mock the repository to test a service class that has dependency on the repository, I’ll let the mocking framework, e.g. RhinoMock, to create completely ‘fake’ repository instance, and this repository simply returns hard-coded entity (or entities) when a method to retrieve entity on it gets called, or update/delete the hard-coded entity when that service calls a method to update/delete entity. This means no hitting database at all.

      BTW, notice that the latest version of repository’s constructor does not depend on ObjectContext anymore, which is also stated in the post.

      Regarding multiple models, thanks for the links, I’ll look at them. However, now I am using code first approach so I don’t have problem with EDMX designer since I don’t use it to generate model from database because I dont have a database yet. If, coding all POCO objects and writing mapping classes is time consumed, then the tool like T4 Template should be employed to automate the work.

      Very interesting comment, though.

      • Huy,

        Thanks for the information regarding your mocking strategy, I’ve been meaning to look into RhinoMock.

        Ok, I knew about the change in the code, but for some reason I was thinking about the earlier version.

        Eventhough you are using code-first, you can still experience performance issues with large models as the problem is not specific to the model designer. With code first, you avoid the design time performance but not the run time performance. So splitting up large models may still be necessary.

        Julie Lerman’s article (the second link in my post above) about the large model issue contains a link to another site which provides an essay and video on the subject which is probably more insightful than the first two articles.

        Thanks again. This has been an interesting article and I will certainly keep my eyes open for any future EF related articles you may write.

  18. Hi, thanks for the post. Is there a way to store the context without using the EF CTP? I’d like to re-use your GenericRepository based on any objectContext.

    • Henry,

      In my experience, it’s quite tricky to abstract the ORM framework or any data access technology within the repository. Let’s say we want to abstract the ObjectContext which in the run time, the concrete instance is NHibernate Session. However, AFAIK, NHibernate Session does not perform well with lambda expression, although there is Linq to NHibernate but at the moment it is still an experiment of Ayende. This causes repository’s methods which use lambda expression failed or do not return the correct result.

      That’s the reason why the repository has a dependency to EF’s ObjectContext to do its job. But if you still want to reuse the repository based on any object context, then the way to go is abstracting the object context, then implement the method to get object context within the repository to have it returns the concrete instance of object context that you implemented. That’s what I can think of at the moment. But if you have a better solution for that, please share with me :)

  19. HI huyrua,
    Thanks for a great piece of code. I really liked it.
    Hey huyrua, we r planning to use EF 4.0 in Sharp Architecture. In latest version of 1.5.2 of Sharp they have NHibernate. We are trying to plug EF4.0 instead of NH. Do you have some sample code for it.
    Thanks again.

    • Venu,

      Sharp Architecture is a great framework that I am using in some of my own projects and never thought that I should use EF in place of NHibernate.

      I think the sample code can be used in place of NHibernate in Sharp Architecture, but it takes time. If you have enough understanding on Sharp Architecture code, you will find there are some points that this sample code can be used in some places of the Sharp Architecture, e.g. ObjectContextInitializer is same as NHibernateSessionInitializer, ObjectContextManager look like NHibernateSession, the EF GenericRepository can be the one in place of NHibernateRepository, and so on. So, although I don’t have a sample code which works with Sharp Architecture, I hope these points are good starts for you if you are interested in :)

      • thank you very much huyrua,
        yes i need to do some modification using your basic code of ef 4.0.

        Thanks again.

  20. When instantiating a repository I have the habit to give a unitOfWork.
    The constructor of the CustomerRepository is like the following
    public CustomerRepository(IUnitOfWork unitOfWork)

    How is it possible to create different unit of works in your sample?
    The purpose is that the developer can choose which actions belongs to a certain unit of work. It must be possible to create several unit of works. Each unit of work will behave as a transaction. Everything of this unit of work will be comitted or nothing and may have no influence on other uow’s.

    • Alef,

      The current implementation does not allow to create different unit of work. Since I have been working mostly with Web applications and WCF services so the common practice applied here is to use only one unit of work per request. Someone also called it Open-Session-In-View design pattern to leverage lazy loading of an ORM framework: start/open a transaction at the beginning of a request then end the transaction after a request is served. With EF, as said in the post regarding unit of work, I dont need to explicitly start a transaction but only need to call SaveChanges() method on the ObjectContext to end the transaction.

      I haven’t had any problem with this implementation so far in the context of Web and WCF since I don’t have a need to create many unit of work to serve a request. Your case seems to be a special one, at least to me. If you have an obvious scenario that requires to create many unit of work, please let me know and I will be very happy to update the implementation to meet that need.

      • Thanks for your reply. I’ve never met a case where it is necessary to have different uow’s, but I have the habit to do this because most of the blogs implement this like this. I’ve never asked myself why. Thanks for given this insight. So for the moment I don’t need this. When I’ll be in this situation I’ll let you known.

  21. If I use the strategy pattern as you’ve laid it out above, EF does not add the criteria to the SQL it generates. Instead, EF queries the entire table and then executes IsSatisfiedBy(T) on each result returned from the database. Am I missing something, otherwise, this pattern seems pointless for EF?

    • Thanks for comment. I need to double check it with a profiler.

      • It’s obviously a bug. The IQueryable#Where method should be fed with an expression tree, not a delegate.

      • @Buu,

        Not sure I am following you. The code is compilable and passed the test (yes, just a simple test). Am I missing something?

      • Linq to Entities uses expressions to build the SQL that will be executed on the database server. If you use the specification pattern as designed above, i.e., without expressions, the generated SQL is never impacted. Instead, EF will generate “SELECT * FROM Table,” returning all rows. From there the specification pattern kicks in and filters the data in memory. Your test passed because you got the right result, but not in the right way. it would never work in a real would scenario.

        Hate to be a wet blanket because it looked so promising at first sight.

        Thanks

      • @Huy: I didn’t mean compilation error. The cause of the issue as Jon observed is because the method (IsSatisfiedBy) of Specification is fed into the Where method of the query object. That results in LINQ-2-EF loading all records to memory objects and then filter those objects using the passed in method. That’s a huge performance hit.

        To fix the issue, you should feed into the Where method an instance of Expression so that the Where overload in IQueryable is invoked (instead of the one in IEnumerable). The Specification already stores an instance of Expression, so the code change should be straightforward. However, since not all expression operations are supported by LINQ-2-EF, you might end up breaking some existing code. Be warned :).

      • I understand the problem now. Thanks Jon & Buu for pointing it out. I need to find a better solution for it.

  22. HI huyrua,

    I have a question about transaction (out of scope of this post),
    How we can manage 2-phase commit using EF. for example i am using EF and WCF (which is deployed on different sever). How we can manage this distributed transaction. Please help me.

    Thanks & Regards,
    Venu

    • Well, it’s a strange and complicated scenario IMO. I think even EF is deployed on a separate server but it should be run be hind a server technologies, e.g. asp.net or wcf, etc. This approach helps the transaction management become a bit easier.

      AFAIK, WCF has transaction management capabilities which allow transaction management to be done across application domains. Not sure if it suits your case, but you can give it a try.

  23. i would like to say my feeling about this article in just one word..

    EXCELLENT…

  24. I reimplemented the Specification pattern addressing the concern from Jon & Buu. I also posted an article for it. Check it out at http://huyrua.wordpress.com/2010/08/25/specification-pattern-in-entity-framework-4-revisited/

    Thanks.

  25. I was trying to use WCF Data Services.

    The following article is based on CTP4 and I was trying to implement this:

    http://romiller.com/2010/07/19/ef-ctp4-tips-tricks-wcf-data-service-on-dbcontext/

    But in your example I don’t find a class which is derived from DbContext.
    Can you provide a little code example how do this with your framework?

    • Alef,

      Check out the lab version at: http://code.google.com/p/ef4prs/source/checkout. I have implemented the DbContext related stuff which can be use in place of ObjectContext. There also is a test class in the test project which you can give it a try.

      Cheers.

      • Hello huyrua,

        I’ve downloaded your example.
        But when looking closer I don’t think it is necessary to create the DbContext stuff, because DbContextManager.Current returns an DbContext instance, but from that instance I don’t see how to get the underlying context. (DbContext uses an ObjectContext internally but this a protected property). In the link http://romiller.com/2010/07/19/ef-ctp4-tips-tricks-wcf-data-service-on-dbcontext/
        they create explicitly a BlogContext which inherits from DbContext so in BlogContext you have access to the protected property ObjectContext). But apparently you are not creating such a class as BlogContext. Why is this not necessary in your framework?

        With ObjectContextManager.Current we immediately have the ObjectContext. So problem solved.

        I’ve created a sample Web project and added a WCF Data Service item and set this as the Start Page.


        using System;
        using System.Collections.Generic;
        using System.Data.Services;
        using System.Data.Services.Common;
        using System.Linq;
        using System.ServiceModel.Web;
        using System.Web;
        using System.Data.Objects;
        using Infrastructure.Data;
        using Infrastructure.Tests.Data.Repository;
        using Infrastructure.Tests.Data.Domain;

        namespace WebApplication1
        {
        public class TestDataService : DataService
        {
        // This method is called only once to initialize service-wide policies.
        public static void InitializeService(DataServiceConfiguration config)
        {
        config.UseVerboseErrors = true;

        // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
        // Examples:
        config.SetEntitySetAccessRule("Customers", EntitySetRights.AllRead);
        // config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All);
        config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
        }

        protected override ObjectContext CreateDataSource()
        {
        ObjectContextManager.InitStorage(new SimpleObjectContextStorage());
        ObjectContextManager.Init("DefaultDb", new[] { @"C:\svn\ef4prs\Infrastructure.Tests\bin\Debug\Infrastructure.Tests.dll" }, true);

        ICustomerRepository customerRepository = new CustomerRepository();
        var c = new Customer { Firstname = "John", Lastname = "Doe", Inserted = DateTime.Now };
        customerRepository.Add(c);
        customerRepository.SaveChanges();

        var ctx = ObjectContextManager.Current;
        ctx.ContextOptions.ProxyCreationEnabled = false;

        return ctx;
        }
        }
        }

        But when starting the web page I get the following error ==> when executing the line customerRepository.Add(c)

        The server encountered an error processing the request. The exception message is ‘Schema specified is not valid. Errors: The mapping of CLR type to EDM type is ambiguous because multiple CLR types match the EDM type ‘Category’. Previously found CLR type ‘Infrastructure.Tests.Data.Domain.Category’, newly found CLR type ‘Infrastructure.Tests.Data.Domain.Category’.

        Maybe I don’t understand where to initialize the ObjectContextManager and where to create some test data.
        Can you modify your example to include a sample Web Page with this WCF data service implementation?

      • Alef,

        I am not creating an XYZContext just because I don’t want to implement such specific object context every time the framework is used with a specific model because if the model has too many entities, this will lead to writing too much get/set properties, e.g. ‘public ObjectSet Blogs’, ‘public ObjectSet Posts’, and so on. Instead, I let the ObjectContextBuilder build the ObjectContext from mapping assemblies fed in, which contain entities (POCOs) and also the mapping classes inside. The idea is for greater reuse. As you can see the framework can be use with any entity data model without the need to implement any specific XYZObjectContext.

        Regarding the DbContext-related stuff in the source code, as said, it’s just a laboratory I created to see whether it can be used in place of ObjectContext, and it has been proved that it can be. However, I am not intend to replace ObjectContext by DbContext because ObjectContext is enough for me now.

        About the error, it may because there were two entities with the same name ‘Category’ found. You might want to refer to the similar error mentioned here: http://blog.zoolutions.se/post/2009/05/29/Entity-Framework-4-POCO-tutorial-Part-1.aspx

        For WCF data service, since I don’t have experience with this technology so I am afraid that I can’t help you much on this. But I’ll keep it in my research list. When I find a solution to integrate the framework with your WCF data service, I’ll get back to you.

        Thanks.

  26. Thanks for the clarification that you are not creating an XYZContext. With this we’ll need to write less code which is always good. Super!

    I didn’t found an solution for the exception message : ‘Schema specified is not valid.
    I’ve did a workaround and initialized the data in the database in place of in code

    So I have the following code :

    namespace WebApplication1
    {
    public class TestDataService : DataService
    {
    // This method is called only once to initialize service-wide policies.
    public static void InitializeService(DataServiceConfiguration config)
    {
    config.UseVerboseErrors = true;

    // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
    // Examples:
    config.SetEntitySetAccessRule("Customers", EntitySetRights.AllRead);
    //config.SetServiceOperationAccessRule("GetCustomers", ServiceOperationRights.All);
    config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
    }

    protected override ObjectContext CreateDataSource()
    {

    ObjectContextInitializer.Instance().InitializeObjectContextOnce(() =>
    {
    ObjectContextManager.InitStorage(new SimpleObjectContextStorage());
    ObjectContextManager.Init("DefaultDb", new[] { @"C:\svn\ef4prs\Infrastructure.Bus\bin\Debug\Infrastructure.Bus.dll" }, false);
    });

    var ctx = ObjectContextManager.Current;
    ctx.ContextOptions.LazyLoadingEnabled = false;
    ctx.ContextOptions.ProxyCreationEnabled = false;

    return ctx;
    }
    }
    }

    When starting the WebApplication eveything OK. I get the following response

    -
    -
    Default
    -
    Customers

    When typing in the browser a second request like the following http://localhost:11650/TestDataService.svc/Customers
    I get an error:
    The server encountered an error processing the request. The exception message is ‘The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.’

    I’ve found a solution after a long time searching.
    I’ve replaced
    ObjectContextManager.InitStorage(new SimpleObjectContextStorage());
    with
    ObjectContextManager.InitStorage(new WebObjectContextStorage(HttpContext.Current.ApplicationInstance));

    and now it is working.

    Can you explain a little bit more the difference between SimpleObjectContextStorage and WebObjectContextStorage?

    • Alef,

      WebObjectContextStorage is used in the context of web application to store object context _per request_. It hooks up the Application_BeginRequest event to store the object context to make the it available in the middle of http request processing, e.g. in the controller action method of an ASP.NET MVC application, then frees the object context in the Application_EndRequest event. The use of WebObjectContextStorage has been commented in the class definition and I hope that it has clearly explained how to use it. The SimpleObjectContextStorage, on the other hand, is also used to store object context but it is not included a mechanism to free/close object context. In the real world, this object should only be used in the Windows application which applies the Open Session In View design pattern.

      In your sample, you are using WebObjectContextStorage and it works fine because your WCF data service is asp.net compatible, so you have the HttpContext instance in the request processing that can be used to store and freed the object context as explained above. It’s interesting to me because I don’t have much experience on WCF data service and I think I should check it out to learn something from it. Thanks :)

  27. Thanks for sharing you code, I just ran across several articles/blog posts on using repository pattern with EF4.0 too. There is another long and detail post on this topic with lots of code at http://www.kitchaiyong.net/2009/10/repository-specification-unit-of-work.html. Basically the blog author has implemented a same solution as yours, except some minor points such as utilizing generic repository via composition instead of inheritance, lacking of explicit composite specification etc.

    BTW, I’m a bit curious about the following content under “The Specification Pattern” section, is there any relationship between those posts? You know, it cautch my eyes since it took me about 40 minutes to read such a long post and I must admit that it is not easy to understand topic.

    “The Specification pattern

    According to Martin Flowler, the idea of Specification is to separate the statement of how to match a candidate, from the candidate object that it is matched against. As well as its usefulness in selection, it is also valuable for validation and for building to order. You can also follow the Specification white paper by Martin Flowler if you want to indulge yourself deeply into this programming pattern.

    In simple terms, it is a small piece of logic which is independent and give an answer to the question “does this match ?”. With Specification, we isolate the logic that do the selection into a reusable business component that can be passed around easily from the entity we are selecting.”

    • I also read a lot of posts about EF 4 before writing this and it might be the post that I ran across and found something to mix in this post. So there may be some overlap information between those. Thanks :)

  28. Firstly I wanted to compliment you on a really great and highly informative post. Certainly the most practical discussion of implementing a repository pattern that I have come across on EF4.
    I have implemented it for a project that I have been working on and it has worked flawlessly with one exception that I was hoping you could shed some light on.
    If I call repository.Update() on a modified entity that inherits from an abstract base class the SQL database complains that the “INSERT statement conflicted with the FOREIGN KEY constraint” associated with the base class . If I bypass the repository and just access the ObjectCcontext directly it works fine.
    Any ideas?

    • PauIE,

      I am not sure if you are using the latest version. I found a bug on the Update method and fixed it lately. In short, now you just call reporitory.Update() and then repository.SaveChanges() then everything would be fine.

      Thanks.

      • I tried that but I still have the problem. I also managed to narrow it down to the GenericRepository class.
        If I make the ObjectContext property in GenericRepository public I can do the following which works:
        ObjectContext context = new GenericRepository().ObjectContext;
        ObjectSet osMeters = context.CreateObjectSet();
        Meter meter = osMeters.First(m => m.MeterId == id);

        … make some changes to the meter entity….

        context.AcceptAllChanges();
        context.SaveChanges(); // This works fine and saves to the db

        If however I do it like this:
        GenericRepository repository = new GenericRepository()
        Meter meter = repository.First(m => m.MeterId == id);

        … make some changes to this meter entity….

        repository.Update(meter);
        repository.SaveChanges();
        // This now throws “INSERT statement conflicted with the FOREIGN KEY constraint” error

        However this only seems to happen when the entity being updated inherits from an abstract base class, and the foreign key constraint on the base class is the problem. In the above code a “Meter” is the abstract base, a concrete subclass may be “GasMeter”, but Meter has a FK association with the “Property” it is located in. Hope this makes sense.

      • Sorry second line of the working version should of course have read:
        ObjectSet osMeters = context.CreateObjectSet();

      • Very sorry – final post to clarify. The angle brackets are being stripped out of my post so the class
        Meter should of course appear within angle brackets on the second line on either side in order for this to compile.

      • PauIE,

        I haven’t had same problem as yours because I don’t have a scenario that needs to abstract entities, so I don’t have a strong opinion on this. Maybe it is the feature of EF, maybe a bug/limitation of the current repository implementation, or the incorrect mapping between entities.

        However, if this one works for you as described:

        context.AcceptAllChanges();
        context.SaveChanges(); // This works fine and saves to the db

        Then instead of making ObjectContext public, you can add AcceptAllChanges() as a method on the repository:

        public void AcceptAllChanges()
        {
        ObjectContext.AcceptAllChanges();
        }

        Then you can calls this method between Update() and SaveChange():

        repository.Update(meter);
        repository.AcceptAllChanges(); // call this before calling SaveChanges()
        repository.SaveChanges();

        Another possible option is to include the method AcceptAllChanges() within the SaveChange() method:

        public void SaveChanges()
        {
        ObjectContext.AcceptAllChanges(); // call this before save changes is invoked
        ObjectContext.SaveChanges();
        }

        repository.Update(meter);
        repository.SaveChanges();

        I hope this make sense for you.

  29. huyrua,
    Can you please provide me overload for Init method.
    Actually i dont want to map the entities using CTP4. I want normal edmx with POCO’s.
    Please help me.
    I want to use objectcontext of normal mapping.

    Thanks & Regards,
    Venu

    • Venu,

      It seems this framework does not suit your need, please see my last comment on Alef Auman to know the reason.

      If you want to use edmx with POCO then you can refer to the implementation of Mikael Henriksson: http://blog.zoolutions.se/post/2009/03/26/Generic-Repository-for-Entity-Framework.aspx

      Hope this help.

      • huyrua,
        I have created class for ObjectContextBuilder which implements IObjectContextBuilder. It is specifically for using edmx. Please verify and let me know your comments.
        public class ObjectContextBuilderForEdmx : IObjectContextBuilder where T : ObjectContext
        {
        private ObjectContext _ObjectContext;
        public ObjectContextBuilderForEdmx(string connectionStringName, string[] mappingAssemblies, bool recreateDatabaseIfExists, bool lazyLoadingEnabled) {
        AddConfigurations(connectionStringName, mappingAssemblies, recreateDatabaseIfExists, lazyLoadingEnabled);

        }

        ///
        /// Adds mapping classes contained in provided assemblies and register entities as well
        ///
        ///
        private void AddConfigurations(string connectionStringName, string[] mappingAssemblies, bool recreateDatabaseIfExists, bool lazyLoadingEnabled) {
        if (mappingAssemblies == null || mappingAssemblies.Length == 0) {
        throw new ArgumentNullException(“mappingAssemblies”, “You must specify at least one mapping assembly”);
        }

        foreach (string mappingAssembly in mappingAssemblies) {
        Assembly asm = Assembly.LoadFrom(MakeLoadReadyAssemblyName(mappingAssembly));

        foreach (Type type in asm.GetTypes()) {
        if (!type.IsAbstract) {
        if (type.IsSubclassOf(typeof(ObjectContext))) {
        ObjectContext instance = Activator.CreateInstance(type,”name=”+connectionStringName) as ObjectContext;
        instance.ContextOptions.LazyLoadingEnabled = lazyLoadingEnabled;
        _ObjectContext = instance;
        break;
        }
        }
        }
        }

        if (this._ObjectContext == null) {
        throw new ArgumentException(“No mapping class found!”);
        }
        }
        public T BuildObjectContext() {

        // calls ModelBuilder.CreateModel() to create DbModel, then uses it to create ObjectContext
        var ctx = (T)_ObjectContext;
        return ctx;
        }

        ///
        /// Ensures the assembly name is qualified
        ///
        ///
        ///
        private static string MakeLoadReadyAssemblyName(string assemblyName) {
        return (assemblyName.IndexOf(“.dll”) == -1)
        ? assemblyName.Trim() + “.dll”
        : assemblyName.Trim();
        }
        }

      • Venu,

        My understanding about your case is that if you want to use edmx, you has already generated the object context from an existing database. For instance, if you have Northwind database, you generate edmx from that database and it results to a so-called NorthwindEntities which already inherits from ObjectContext class. This is not the way the framework is being implemented because I am using model first development: not generating the object context, in this case the NorthwindEntities, from an existing database.

        If my understanding is right then you do not need to use ObjectContextBuilder because you already has the NorthwindEntities (also is the ObjectContext). What you only need to do is to implement another generic repository which accepts the NorthwindEntities. Then in the repository implementation methods, you just forward the call to this NorthwindEntities to perform the CRUD operations for you. Once again, please refer to Mikael Henriksson implementation which I think is best suit your need – http://blog.zoolutions.se/post/2009/03/26/Generic-Repository-for-Entity-Framework.aspx. Or you may also want to check out another implementation from here http://geekswithblogs.net/seanfao/archive/2009/12/03/136680.aspx (also read through the comment from Sean Pao which propose a way to create ObjectContext using a class named DatabaseUtitlity)

        Hope this help.

  30. Have you seen the pattern from Shrinkr.codeplex.com?

  31. Huyrua,
    As you know SharpArchitecture. Can you tell me equivalent class in EF4 for “EntityDuplicateChecker.cs” of NHibernate implementaion in Sharp Architecture.

    Thanks in advance.

    • Sorry if i am bothering you.

    • Do you have any reason for using it? I never thought I would need that class with EF implementation.

      • As we have developed EF specific code in SharpArchitecture…comparing NHibernate specific(which is the default implementation)…..our other code is now working …with the help of your infrastructure code….only thing remaining is EntityDuplicateChecker.cs (specific to EF)…..shall i send my EntityDuplicateChecker.cs to you….so that you suggest me a solution.

      • I checked the SharpArch code and found the EntityDuplicateChecker is being used to find duplicate entities managed by NHibernate’s Session. IMO, we don’t need this class with this EF implementation but if you still want to implement it for some of reasons, the logic of EntityDuplicateChecker is not very complicated and I believe you can implement when you understand the code.

        Hope this help.

      • Yeah it is simple…we also convert it …but one big problem is i can not pass concrete entity class name to IQueryable and expression. if you look at following code…how can i replace.
        As i am getting entity from parameter like public bool DoesDuplicateExistWithTypedIdOf(IEntityWithTypedId entity)
        IEntityWithId with concrete class name…..it is the problem.

        IQueryable<IEntityWithTypedId> query = session.CreateQuery<IEntityWithTypedId>(entityName);

        Expression<Func<IEntityWithTypedId, bool>> criteria = AppendSignaturePropertyCriteriaTo(_first, entity, c);

        As you can see in generics we have to pass something class/interface…please help me….if you want me to send the whole code. how can send …shall i paste in this blog.

      • Venu,

        I did consider your problem but I have to say I can’t help you right now because the problem might take me to go deeply on the SharpArchitecture’s code while I have no spare time for that.

        With big regret.

      • Huyrua,
        No need to regret, whatever you provided in Infrastructure…is very very valuable…
        I know you are providing this help despite regular work.
        Waiting for your reply.
        Thanks for the infrastructure code again.

  32. It’s very useful. Do you have any idea how to map an Enum?
    Thanks

  33. Hi Huy,
    Two excellent blog entries. Code first seems an exciting prospect and your library is very good.
    I’m hoping you can help as I’m having the same issue as Alef earlier –
    I get a schema invalid error –
    The mapping of CLR type to EDM type is ambiguous because multiple CLR types match the EDM type ‘Term’. Previously found CLR type ‘Engage.Data.Domain.Term’, newly found CLR type ‘Engage.Data.Domain.Term’.

    I’ve removed all other classes in my domain so that I just have Term which inherits from EntityBase and TermMapping. I’ve referenced against your test cases and I’m lost!

    I read the blog you mentioned in your reply but it refers to a situation where there was the same classname in two different namespaces. My code does not have that situation. I’ve a library called Engage.Data with a domain folder containing the term class and the term mapping. Does it make a difference where you create the domain model and the object manager? In your test examples you instantiate the ObjectContextManager in the same library as your domain model?

    • I’ve come across the error once but I haven’t yet figured out under exactly what circumstances it occurs. I seems to be an issue with current version of EF. What I did was renaming the entity to something ‘unique’.

      Regarding the ObjectContextManager, I am not sure if I understand your question but I think it does not make any issue whether ObjectContextManager is in the same assembly with model objects or not.

      Sorry, I cannot be much help.

  34. Hi, not kinda related with patterns u described but i’ll be glad if u can help.
    I have all my model classes inherit from EntityBase class which only has property Id. First error i got was when i used “HasKey(x=>x.Id)” in EntityBaseMapping class and it was something like this:

    The property ‘Id’ of type ‘Odvjetnik.Model.POCO.EntityBase’ is redefined on type ‘Odvjetnik.Model.POCO.Faze’. Property hiding is not supported.

    Then i used “Property(x => x.Id).IsIdentity();” in EntityBaseMapping, and it passed smoothly, but when i looked at DB every entity was mapped into one single table dbo.EntityBases.

    I checked my POCO and Mapping classes and they seem OK, guess it has to do with inheritance mapping and i was expecting TPT as default, but it seems it isn’t. Hope u can help.

    P.S. I’m kida beginner so don’t mind if this is really stupid that i wrote.

    • I guess that your Faze object also has an Id property while it shouldn’t just because it inherits from EntityBase class.

      • It doesn’t i double checked, but when i put Id in every class and removed it from EntityBase everything worked perfect. Suppose i’ll just leave it that way.

      • I cannot figure out what the problem is so if you found a way to make it work for you then you can go with it.

  35. One question about the ObjectContextFactory implemetation on this post: Why do you require mappngAssemblie? If the POCO objects are simple enough to be able to use the “convention over confiration” aspect of EF4 Code-First, couldn’t you just check for zero mapping assemblies, and if that’s the case, simply retun from the method and let EF do it’s thing in creating the model? Or am I mixing up things between ObjectContext and DbContext?

    Also, looking at the Lab stuff for a DbContext imlementatio on GoogleCode, anywhere you feel the need to return an IQueryable<TSomething>, you can simply return the DbSet<TSomething>, as it inherits from IQueryable<T>. Or is there something else I’m missing? ;)

    BTW, a most execellent post (including your revised Specification Pattern post). Very helpful! Thanks for your time on this series of posts, it looks like it has helped a lot of people, including me.

    • The post had been published before DbContext was released with CTP4, that’s why there is a Lab version that I tried to play with it. So, yes, you are mixing up ObjectContext and DbContext. ;)

      Regarding the Lab version, for the method GetQuery, you are right that we can return DbContext.Set because it inherits from IQueryable. No need to call .AsQueryable() on the DbSet.

      Thanks for comment.

  36. Two more things:

    1) Bear with my spelling…web browsers, when they get bogged down (esp. with lots of JS running in the background) miss half the characters I type.

    2) I see you making use of the PluralizationService. How does this affect EF4 Code-First if I have aconfiguration/mapping class that contains, say:


    // Pretend we're in a class that is derived from EntityConfiguration inside the constructor definition...
    this.MapToSingleType().ToTable("MySingularTableName");

    What happens with your code as you’ve designed it above?

    Thanks again!!!

    • Pluralization service is used to make entity name plural, as it is required by ObjectContext when register object set.

      You can use this.MapToSingleType().ToTable(“MySingularTableName”) in the mapping class to explicitly tell EF to create the table with name “MySingularTableName”. If you don’t, EF will use object set name to generate table’s name. I always use this method to explicitly tell EF to generate expected columns names. In other words, MapToSingleType(….).ToTable(“TableName”) is highly recommended to be used to create prefer table/column names.

  37. Using your implementation of repository pattern i got this error:
    Multiple object sets per type are not supported. The object sets ‘Models’ and ‘Cases’ can both contain instances of type ‘Lawyer.POCO.Model’.

    *this is not part of error, just how the classes are modelled)
    (Case:EntityBase; Model:Case –> inheritance, TPT)

    The solution i found here:
    http://social.msdn.microsoft.com/Forums/vi-VN/adonetefx/thread/ea563dd9-7314-4b6b-8f1f-da3eb095a266
    saying that MapHierarchy will automatically create a single entity set without calling RegisterSet. In your solution you use RegisterSet, and i need MapHierarchy for TPT inheritance modelling. And then the error pops up :) I’m really tight on schedule here and really would like to use your implementation of pattern (because is the best one out there :) so do you have any suggestion how to solve this?

    And another question: Will using MapHierarchy also override pluralization in your case? Because of error I cannot create database to check, but the error clearly shows that pluralization kicks in, so i guess not?

    • Hi, me again :)

      Kinda solved it, although not the most generic solution in the universe (will do for the designing and testing phase), just added additional condition before the RegisterEntity call:

      if (entityType != null && !(typeof(Case).IsAssignableFrom(entityType)))
      {
      RegisterEntity(entityType);
      }
      ….
      And the MapHierarchy does override pluralization.

      If u have any other suggestions, would gladly hear about it.

      Thx again for an excellent article.

      • Tom,

        I am not using MapHierarchy in a mapping class but MapSingleType instead to map entity to a table name and also explicitly map its properties to prefer column names. And yes, using MapSingleType overrides pluralization of entity sets. You might also want to see my comment on Craig Shea’s which is just above your comment (the latest source code on google code also demonstrates it)

        Regarding the error “Multiple object sets per type are not supported…” which is related to entity inheritance, I do see the problem but at the moment I don’t know how to resolve it in a generic way. It maybe a limitation of the current implementation or the EF itself. I will try to fix it when I have some spare time.

        Hope this help.

  38. First of all thx for your great work!

    I was experimenting and also had a problem with inheritance, like in following

    public class BaseClass : EntityBase
    {

    }
    public class InheritedClass : BaseClass { }

    there are separate mapping for both classes (separate tables)

    • Sorry, I accidentaly hit the post commenct :(

      So when using like this then the ObjectContextBuilder will try to register a dbset for both types and then I get the error Tom posted.
      I solved it by defining a custom Attribute

      [AttributeUsage(AttributeTargets.Class)]
      public class IgnoreEntityAttribute : Attribute
      {
      }

      and in ObjectContextBuilder i made the following change

      private void RegisterEntity(Type entityType)
      {
      var ignoreEntity = entityType.GetCustomAttributes(true)
      .Where(a => a is IgnoreEntityAttribute)
      .FirstOrDefault();
      if (ignoreEntity == null)
      {

      var pluralizedSetName = _pluralizer.Pluralize(entityType.Name);

      // using reflection to invoke the generic method RegisterSet(string setName)
      this.GetType()
      .GetMethod(“RegisterSet”, new Type[] {typeof (string)})
      .MakeGenericMethod(entityType)
      .Invoke(this, new object[] {pluralizedSetName});
      }
      }

      so now my inhterited class looks like
      [IgnoreEntity]
      public class InheritedClass : BaseClass {}

      and it works just fine.

      Did some testing with Silverlight and Ria Services and works superb.

      Btw, i also commented out in the BuildObjectContext method

      //if (!ctx.DatabaseExists())
      //{
      // ctx.CreateDatabase();
      //}
      //else if (_recreateDatabaseIfExists)
      //{
      // ctx.DeleteDatabase();
      // ctx.CreateDatabase();
      //}
      part, as I’m using Firebird and it dosn’t allow to check database existence.

      Zoltan

      • That’s great Zoltan.

        I will consider adding your attribute to the framework in the official release of Entity Framework if Microsoft still keep DbSet.

        Thanks.

  39. I just realize that GenericRepository is really generic. Even though declaration like

    private ICustomerRepository customerRepository;
    private IRepository productRepository;
    customerRepository = new CustomerRepository();
    productRepository = new GenericRepository();

    There’s nothing to stop you from doing
    productRepository.Add(new Category{…})
    or even
    customerRepository.Add(new Category{…})

    Is that what it intended to be? What happens when you save changes? Will CustomerRepositry persists a customer, product and category, all in one transaction?

    Somehow I got the impression, maybe from other samples, that you can declare

    productRepository = new GenericRepository();

    and only allow to add product to product repository.

    I’m not at the level of fully understand all your code behind the scene yet. Did I miss something important? Thanks.

    • Site taking out the bracket. I mean declare

      productRepository = new GenericRepository[Product]();

      • @Whoever

        Is that what it intended to be? >> It is intended to demo the use of specific repository like CustomerRepository and ProductRepository to work with a specific entity like Customer and Product.. In reality, we don’t need to define these repositories, just GenericRepository is enough.

        Will CustomerRepositry persists a customer, product and category, all in one transaction? >> Yes.

        Hope this help.

      • Thanks. Now after the initial shock and awe, turned out that’s the first thing you explained in the article. Silly me!

        It’s a tremendous help for newbies like me that you spend time going through the actual thought process of creating such a wonderful piece. You can’t imagine how many time I have opened up some of the latest and greatest open source projects, totally lost after five minutes and given up.

  40. This maybe another stupid one, but couldn’t help it … … I saw there’s the Attach[TEntity] in the Repository but not sure how it should be used.

    Suppose I have a web page, call WCF, get a customer, change name and call another method to save changes. Do I get a new context, attach the customer and save? Or do I get another copy of the customer and ApplyChanges? Or is it better to go for DTO with POCO/code first (still need to get customer first)?

    Thanks.

    • Attach method has a long story which is related to EF object state manager. You might want to refer to this article for further understanding: http://msdn.microsoft.com/en-us/library/bb896271.aspx. Here is an excerpted:

      “When a query is executed inside an object context in the Entity Framework , the returned objects are automatically attached to the object context. __You can also attach objects to an object context that are obtained from a source other than a query__. You might attach objects that have been previously detached, objects that have been returned by a NoTracking query, or objects that have been obtained outside the object context. __You can also attach objects that have been stored in the view state of an ASP.NET application or have been returned from a remote method call or Web service__”

      Hope this make clear some points.

  41. Hi,

    Now that the CTP 5 has been released, do you plan to update your code for this new version?
    Thanks.

  42. Not sure if I’m missing the obvious again, how do you set eager loading like the commonly quoted example.

    context.Product.include(“Category”)

    I couldn’t figure out how to get hold of the context. Thanks

    • There is an extension method for IQueryable for strongly-type loading related entity located in Infrastructure.Data.EntityFramework\EntityFrameworkExtension.cs. What you need to do is adding an using directive to Infrastructure.Data.EntityFramework then calling the Include() method on IQueryable type. Like below example:

      using Infrastructure.Data.EntityFramework;
      //…

      // find all product which includes Category in only one round trip
      IQueryable products = Repository.GetQuery().Include(p => p.Category);

      // Or, find a product with Id == 123, and eagerly load Category in only one roundtrip
      Product product = Repository.GetQuery().Where(x => x.Id == 123).Include(x => x.Category).SingleOrDefault();

      Hope this help.

  43. That is I need. Your article makes my dummy mind be happy :)
    Thank a lot

  44. Thanks for the great work and the patience with the dummy minded, I’m now officially running my amateur architect sample app 0.1 :-) It’s like WEB => WCF => Business/Entities/Repository => EF4/SQL

    Only one thing, WebObjectContextStorage uses HttpContext, which is not available in WCF. If I don’t want to set AspNetCompatibilityRequirements on the service, do I have to create a separate WcfObjectContextStorage, or is there something simpler? Thanks.

    • Yes, I think you need a WcfObjectContextStorage. If you have time, you can refer to the WcfSessionStorage class in SharpArchitect code base. The class WcfSessionStorage can be ported to this framework as WcfObjectContextStorage, just as you need. The reason for it not being included in this framework is that that class does not run alone but being instantiated by some other classes (ServiceBehavior, InstanceCreationInitializer, InstanceExtension) and the mechanism is very WCF-related while I just want to keep the framework as simple as possible.

      Hope this help.

  45. I’ve been reading about these patterns for a long time and I’m still not convinced that they’re not over-complicating data access. Nevertheless, great article.

  46. Nice collage, all solution in one nut. Great thanks!
    I am really wondering when you will implement and share for EF5 POCO version?

  47. This article is simply the best sample about implementing repository pattern with EF. Thank You!

  1. Pingback: Tweets that mention Entity Framework 4 POCO, Repository and Specification Pattern « Huy Nguyen's Blog -- Topsy.com

  2. Pingback: Context is King

  3. Pingback: Specification Pattern In Entity Framework 4 Revisited « Huy Nguyen's Blog

  4. Pingback: Entity Framework 4 POCO, Repository and Specification Pattern [Upgraded to CTP5] « Huy Nguyen's Blog

  5. Pingback: Entity Framework 4 POCO, Repository and Specification Pattern « ALT .NET Saigon's blog

  6. Pingback: Entity Framework 4 POCO, Repository and Specification Pattern [Upgraded to EF 4.1] « Huy Nguyen's Blog

  7. Pingback: EF Link Drive « Fast .NET

  8. Pingback: Specification Pattern In Entity Framework 4 « talk4dev

  9. Pingback: EF4: Why does proxy creation have to be enabled when lazy loading is enabled?

  10. Pingback: Interesting Blogs on the Specification Pattern « IExtendable

  11. Pingback: EF4: Why does proxy creation have to be enabled when lazy loading is enabled? | PHP Developer Resource

Follow

Get every new post delivered to your Inbox.

Join 58 other followers

%d bloggers like this: