IUnitOfWork how to use - best practice

raydenl picture raydenl · Mar 28, 2012 · Viewed 13.9k times · Source

I'm using EF4.3.1 in a .Net4.0 web forms (not MVC!) application.

I tend to use the repository pattern with an IUnitOfWork interface. But I'm wondering if I'm following best practices, especially since most examples I've followed are based on MVC apps.

I will say it's only a small web app, so that may affect the solution choices.

The solution currently has 3 projects, Model, Logic and Site. Model contains the codefirst entities and the IUnitOfWork interface. Logic contains the repositories and service layer. Site obviously contains the website, codebehind, etc.

I don't use any third-party inject utility (ninject, etc). I manually inject repositories with an IUnitOfWork i.e.

public BookingRepository(IUnitOfWork unitOfWork)

I'm less clear what to do with the service layers, should the IUnitOfWork also exisit in the Site project, or only exist in the Logic and Model layers.

Currently I inject a repository and a unit of work into a service i.e.

public BookingService(IUnitOfWork unitOfWork, IBookingRepository repository, IAppSettings appSettings)

But this means the commiting (save to db) is done at the Site level, but I wonder if it should be done in the service layer. It also means, that since my IUnitOfWork is declared in my model layer, I need a reference to Model in my site also.

What can I do better? Am I doing anything right? lol

Answer

Ben Ripley picture Ben Ripley · Nov 16, 2013

Dmitry is right. Here is a sample implementation of a Unit of work. The benefit here is that the unit of work pattern coordinates the work of the multiple repositories by enforcing a single database context class shared by all of them.

This is a good resource for beginning to understand how these patterns can be used together. It is valid for both MVC and web Forms development. Implementing the Repository and Unit of Work Patterns in an ASP.NET MVC Application

public class UnitOfWork : IDisposable
{
    private DbContext _context;
    private PersonRepository _personRepository;
    private CompanyRepository _companyRepository;

    public UnitOfWork(DbContext context)
    {
        this._context = context;
    }

    public void Commit()
    {
        _context.SaveChanges();
    }

    // We lazy-load our repositories...
    public PersonRepository PersonRepository 
    {
        get
        {
            if (this._personRepository == null)
            {
                this._personRepository = new PersonRepository(context);
            }
            return _personRepository;
        }
    }

    public CompanyRepository 
    {
        get
        {
            if (this._companyRepository == null)
            {
                this._companyRepository = new CompanyRepository(context);
            }
            return _companyRepository;
        }
    }

    //IDisposable implementation removed for brevity...
}