Lifetime of an ObjectContext (DbContext in 4.1)

I first used Entity Framework in a partially developed WinForms application. In this application, the ObjectContext was alive for the lifetime of the form, this was great when it came to change tracking and lazy loading, however there were a few pitfalls.

Memory Usage

Because the ObjectContext was alive for the entire lifetime of the form, every entity which was ever loaded got referenced by the change tracker, this meant that after navigating through lots of records the memory usage grew too large (sometimes causing an OutOfMemoryException to be thrown).

Relationships

When using a shared class, if the class contained any entities, those entities could not be attached and used in the scope of the form without first being reloaded by the local ObjectContext. If the entities were previously detached, then we would have to be sure to detach the entities from the local ObjectContext when finished. If we didn’t take either of these approaches, somewhere along the line we would encounter:

‘The relationship between the two objects cannot be defined because they are attached to different ObjectContext objects’

So with these two problems, and the inclination that an ObjectContext should be treated like a single Unit of Work I decided to produce a decent solution.

The new solution was developed while re-writing the WinForms application in WPF, utilising MVVM with the Prism framework (I’m sure I will blog all about this in future).

IOC

One of the major changes with moving to WPF with Prism was utilising Inversion of Control through Dependency Injection, so the following solution will be making use of Dependency Injection with the the Unity Application Block.

POCO

To reduce the coupling between the data types and Entity Framework, one of the first things I did was make the move to using POCOs (Plain Old CLR Objects). At this point I had started to use EF4.1  which utilises DbContext as a wrapper around an ObjectContext.

To further reduce the links between the DbContext and the entity classes, I disabled both LazyLoading and ProxyCreation inside the DbContext like so:

Configuration.LazyLoadingEnabled = false;
Configuration.ProxyCreationEnabled = false;

This should ensure that Entity Framework does not create a proxy type around the POCOs, the proxy types can be bad as they keep a reference to the DbContext open, even after the DbContext is disposed.

Layers

As the application is N-Tiered, there is a service layer (for business logic), which utilises the repository layer (for CRUD) which then uses the DbContext to actually perform the operations. For this implementation, I decided the service layer is where the Units of Work should be handled, as it is the business rules which should decide if the procedure should commit or fail.

Unit of Work

As the Unit of Work commits the save, it requires a reference to the DbContext to perform the save on, something like:

public void Save()
{
    _dbContext.Save();
}

Although personally, I found I would like to be able to nest Units of Work (much like a TransactionScope), so if you would like to see how I implemented nested Units of Work, comment and I’ll write an post :)

Repositories

Before I got much further, I had a think about how I would like to see the code in the services look when being used, the following is what I came up with:

public void Purchase(Customer customer, Product product, int quantity)
{
    using (var uow = _unitOfWorkFactory())
    {
        var purchaseRepo = // Get the repository somehow;

        var newPurchase = purchaseRepo.CreateNew();
        newPurchase.Customer = customer;
        newPurchase.Product = product;
        newPurchase.Quantity = quantity;

        purchaseRepo.Add(newPurchase);

        uow.Save();
    }
}

The biggest problem I saw here was how to ensure the same DbContext for both the Unit of Work and the repositories. I wanted the DbContext as a constructor dependency in the repository class, as it is 100% required and makes the dependencies clearer, unfortunately Unity doesn’t handle passing parameters to the constructor too well (unless it’s a direct call to IUnityContainer.Resolve).

Solution

My solution was simply to have a Unit of Work implementation which contains these repositories. A simple Unit of Work could look like:

public interface ILzShopUnitOfWork : IUnitOfWork
{
    IRepository PurchaseRepository { get; }
}

public class LzShopUnitOfWork : ILzShopUnitOfWork
{
    readonly DbContext _dbContext;
    readonly IRepository _purchaseRepository;

	bool _disposed;

    public IRepository PurchaseRepository { get { return _purchaseRepository; } }

    public LzShopUnitOfWork(DbContext dbContext, IRepository purchaseRepository)
    {
       _dbContext = dbContext;
       _purchaseRepository = purchaseRepository;
    }

    ~LzShopUnitOfWork()
    {
       Dispose(false);
    }

    public void Save()
    {
        _dbContext.Save();
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool managed)
    {
        if (!_disposed)
        {
            if (managed)
                _dbContext.Dispose();

            _disposed = true;
        }
    }
}

Then by using Unity’s PerResolveLifetimeManager on the DbContext implementation, the repository and the unit of work will get the same DbContext. When the Unit of Work is disposed, the DbContext will be disposed, releasing any handles to the POCOs allowing them to be used with other DbContext instances.

The previous example service method would now look like:

readonly Func<ILzShopUnitOfWork> _unitOfWorkFactory;

public void Purchase(Customer customer, Product product, int quantity)
{
    using (var uow = _unitOfWorkFactory())
    {
        var purchaseRepo = uow.PurchaseRepository;
        uow.CustomerRepository.Attach(customer);
        uow.ProductRepository.Attach(product);

        var newPurchase = purchaseRepo.CreateNew();
        newPurchase.Customer = customer;
        newPurchase.Product = product;
        newPurchase.Quantity = quantity;

        purchaseRepo.Add(newPurchase);

        uow.Save();
    }
}

I hope this is of some use to anyone embarking on Entity Framework and looking for a Unit of Work implementation.

Warning: Any code provided above is purely for example and is not guaranteed to compile but merely provide guidance towards implementation. Some knowledge of Unity and Dependency Injection is probably advised.