2

Previously I have had parameterless repositories being injected into my MVC controllers:

ProjectRepository implementation:

public class ProjectRepository : EntityFrameworkRepository<Project>, IProjectRepository
{
    public ProjectRepository()
    { }
}

UnityConfig.cs dependency resolution:

container.RegisterType<IProjectRepository, ProjectRepository>();

MVC Controller:

private IProjectRepository _projectRepository { get; set; }

public ProjectController(IProjectRepository projectRepository)
{
    _projectRepository = projectRepository;
}

This worked great.

Now I have implemented a Unit of Work pattern into my repository classes so that I can commit transactional changes to data (especially when changes are being made to more than one repository).

The new ProjectRepository implementation accepts a IUnitOfWork in its constructor:

public class ProjectRepository : EntityFrameworkRepository<Project>, IProjectRepository
{
    public ProjectRepository(IUnitOfWork unitOfWork): base(unitOfWork)
    { }
}

This means that multiple repositories can share the same IUnitOfWork and changes can be collectively committed using UnitOfWork.SaveChanges().

QUESTION:

How do I now use dependency injection to instantiate the repository with an instance of IUnitOfWork?

public ProjectController(IProjectRepository projectRepository, IUnitOfWork unitOfWork)
{
    _projectRepository = projectRepository;
    _unitOfWork = unitOfWork;
}

There could also be more than one repository injected into the controller. How can these all be instantiated with the same IUnitOfWork?

Dave New
  • 38,496
  • 59
  • 215
  • 394
  • If you start doing that, you are drifting away from a CRUD application and the amount of logic in your controllers will increase. This is the time to start moving to a different pattern. Move the unit of work and repository to the business layer and inject an abstraction for executing business logic into your controller. In other words: hide the way the request is processed completely from the presentation layer. I suggest using the [command/handler pattern](http://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=91). – Steven Dec 10 '13 at 11:11
  • @Steven: Essentially the repository code would actually sit inside a service class, so it would achieve that (the above code was just an example). But I would be stuck with the exact same problem. The `ProjectService` constructor would be injected with a `IProjectRepository` and an `IUnitOfWork`. How can I ensure that the `IUnitOfWork` instance is then also injected into the `IProjectRepository` constructor? – Dave New Dec 10 '13 at 12:25
  • There is no need to inject IUnitOfWork into the controller if you're already injecting it into your repository. Just register IUnitOfWork with your Container with a PerWebRequest lifestyle so that the same instance is used across all repositories for a single web request. – Facio Ratio Dec 10 '13 at 18:15
  • 1
    Sorry, what I said above is not true, because you must call IUnitOfWork.Commit() somewhere. This is why I also use command handlers. – Facio Ratio Dec 10 '13 at 20:44
  • Related: http://stackoverflow.com/questions/10585478/one-dbcontext-per-web-request-why – Steven Dec 11 '13 at 12:59

1 Answers1

1

When you register your IUnitOfWork instance, use PerResolveLifetimeManager, this will ensure every dependency of IUnitOfWork within a single IUnityContainer.Resolve gets provided the same instance.

For example:

public class SomeDependency
{

}

public class Service
{
    public Service(SomeDependency someDependency, SomeDependency someDependency2)
    {
        Console.WriteLine(someDependency == someDependency2); 
    }
}

public static void Main()
{
    using(var container = new UnityContainer())
    {
        container.RegisterType<SomeDependency>(new PerResolveLifetimeManager());
        container.Resolve<Service>();
    }
}

This will output True to the Console.

See the page for Understanding Lifetime Managers for further details.

Lukazoid
  • 19,016
  • 3
  • 62
  • 85