Neil Hosey
Neil Hosey

Reputation: 465

Unit of Work, Entity Framework DBContext Scope

I've run into a bit of a problem with EF looking for the best practice for this problem:

public void TestEntityFramework_UOWImplementation()
{
    using (UnitOfWorkInventory uow = new UnitOfWorkInventory())
    {
        IMaterialRepository repos = new MaterialRepository(uow);

        Material mat = GetMaterial("Mikes Material", 1);

        mat.CostPrice = 20;

        repos.InsertOrUpdate(mat);

        uow.Commit();
    }
}

private Material GetMaterial(string sku, int clientId)
{
    IMaterialRepository repos = new MaterialRepository(new UnitOfWorkInventory();

    return repos.Find(sku, clientId);

}

In the TestEntityFramework_UOWImplementation() method, its fine, i call create a scope for my unit of work.. and create a repository inside it.

But when i want to getMaterials() as below.. I have no access to the unit of work or the repository, unless i actually pass it as a parameter! This is clearly not particularly nice.

How do people get around this problem??

Thanks in advance!

Neil

Upvotes: 6

Views: 2977

Answers (2)

Neil Hosey
Neil Hosey

Reputation: 465

If anyone was looking for a way around this, I done something a bit different.

I used a Dependency Injection framework (StructureMap) to handle all DI, so everytime i instantiate a repository it will retrieve the DBContext from the Service Locator of StructureMap. I also make the dbcontext scope to be for the duration of the request from the webserver.

The advantage here being that everytime i retrieve or inject a DBContext, it will retrieve the same context for the duration of the request meaning i can use this across multiple methods and class! I pass the interface type as a generic param to the constructor, meaning that i can point the repo as different contexts. Helpful in applications where there are lots of dbcontexts.

Repo Constructor Eg:

public class PurchaseOrderRepository<TDbContext> : GenericRepository<PurchaseOrder>, IPurchaseOrderRepository<TDbContext> where TDbContext : DbContext
{

        public PurchaseOrderRepository()
            : base((TDbContext)ObjectFactory.GetInstance<TDbContext>())
        {
        }
}   

Usage:

 //resolves the request scope InventoryContext... 
var pRepos = new PurchaseOrderRepository<IInventoryContext>();

and the structure map dependency looks like:

    For<IInventoryContext>().HttpContextScoped().Use<InventoryContext>();

Upvotes: 0

Juan
Juan

Reputation: 1144

In your implementation you wont have access to the Unit of Work like that. What I do is use an IoC container and Dependency Injection to handle it. I have a WCF service that uses Unit of Work with a repository pattern against EF5.

You can read more about repository pattern, unit of work, and EF here but basically what I do is in the constructor of my service class I inject the Unit of Work like so:

    private readonly IUnitOfWork uow;

    public LoanService(IUnitOfWork unitOfWork)
    {
        uow = unitOfWork;
    }

Then I can use uow.WhateverMethod in my repos anywhere in the service. I use Ninject to handle the injection of IUnitOfWork. Hope it helps you.

Upvotes: 3

Related Questions