Darren Lewis bio photo

Darren Lewis

Professional Nerd

Twitter GitHub StackOverflow
Published: July 15, 2010

I'm currently working on an ASP.NET MVC application that uses Entity Framework 4 and Unity. This project uses Unity for DI and the Repository and UnitOfWork patterns to abstract the EF as much as possible. I won't cover any detail of the use of the latter two patterns within ASP.NET MVC here as it's been done to death across the internet, at least at a fairly high level.

Each repository takes on its constructor a custom interface implementation reference to my models ObjectContext thus:

Considerable name changing to protect the innocent!

public interface IMyCustomContext
{
IObjectSet<Customer> Customers { get; set; }
IObjectSet<Order> Orders { get; set; }
}

I extract this interface directly off the T4 generated MyCustomContext within Visual Studio and then create a partial class implementation of MyCustomContext and implement this interface. Of course I don't have to do any implementation as this has already been taken care of in the T4 created MyCustomContext. I do however then implement an IUnitOfWork interface on my partial implementation. This has just one method on it called Save(). The implementation within my partial simply calls the SaveChanges() method on MyCustomContext.

Ignoring the specifics of the repositories they each they take an implementation of this interface on their constructor. There's another post I need to get done regarding why I send in the entire context rather than just the IObjectSet as many other samples have shown.

OK that's a whole lot of text that's nothing to do with the title of this blog but I think it gives better context (geddit!) to the next section.

The repository and context are used within my MVC site Controllers has constructor dependencies supplied by Unity and here's where we finally get to the LifetimeManager!

Sample Controller:

public class CustomerController : Controller
{
    private readonly ICustomerRepository _repository;
    private readonly IUnitOfWork _unitofwork;

    public CustomerController(ICustomerRepository repository, IUnitOfWork unitOfWork)
    {
        _repository = repository;
        _unitofwork = unitOfWork;
    }

    [HttpPost]
    public ActionResult Details(Customer customer)
    {
        if (ModelState.IsValid)
        {
            _repository.Add(customer);
            _unitofwork.Save();
        }

        return View();
    }
}

 

Ignore the fact that there is actually only one piece of work (save) happening here. The idea of the UnitOfWork is that it ties together multiple changes and commits these to your datastore as a single transaction (unit of work). Imagine perhaps that we've saved an order also.

So how are the repository and the unitofwork linked? Well remember the unitofwork is just an interface into our MyCustomContext POCO class and the repository was passed an instance of MyCustomContext by Unity. Within Unity configuration both IUnitOfWork and the IMyCustomContext constructor dependency for ICustomerRepository both resolve to MyCustomContext. However, with the default TransientLifetimeManager used within Unity each will get its own instance of MyCustomContext. This will almost certainly manifest itself as your code running successfully but nothing appearing in the database as the context called through unitofwork has no changes against it. The changes are in the context held within the repository.

I first tried solving this problem by defining the LifetimeManager for the MyCustomContext as singleton. However, this causes the context to throw an exception when you try and save due to a transaction issue. What we needed was a way of telling Unity that for each Http Request we'd like it to use the same context. This is achieved with the following custom Http Context Unity LifetimeManager:

 

    public class HttpContextLifetimeManager<T> : LifetimeManagerIDisposable
    {
        public override object GetValue()
        {
            return HttpContext.Current.Items[typeof(T).AssemblyQualifiedName];
        }

        public override void RemoveValue()
        {
            HttpContext.Current.Items.Remove(typeof(T).AssemblyQualifiedName);
        }

        public override void SetValue(object newValue)
        {
            HttpContext.Current.Items[typeof(T).AssemblyQualifiedName] = newValue;
        }

        public void Dispose()
        {
            RemoveValue();
        }
    }

 

The final piece in the puzzle for me was getting this to work with Unity design time configuration. The generic T in this code needs to represent MyCustomContext but how do you define generics in config. QED it would seem as follows:

 

      <register type="IMyCustomContext" mapTo="MyCustomContext">
        <constructor/>
        <lifetime type="HttpContextLifetimeManager`1[MyCustomContext]" />
      </register>

 

I hope this proves useful to someone. Any questions, comments or berates feel free to drop me a line.