2

I have implemented a generic Repository and UnitOfWork found here.

My server-side stack is: C# .Net 4.5, EF6, AutoMapper (for EF model/DTO), Autofac (DI), WebAPI, OData.

My DI setup is as follows:

var builder = new ContainerBuilder();

builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());                        // using extension to register all controllers in an assembly at once
builder.RegisterType<ProjectV001Context>().As<IDataContext>().InstancePerHttpRequest();
builder.RegisterType<Repository<ContentType>>().As<IRepository<ContentType>>().InstancePerHttpRequest();
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerHttpRequest();

builder.RegisterType<ContentTypesController>().As<IContentTypesController>().InstancePerHttpRequest();

var container = builder.Build();

Here is my OData controller:

public class ContentTypesController : ODataController, IContentTypesController
{

    // add repository reference
    private readonly IRepository<ContentType> _repository;

    private ProjectV001Context _db = new ProjectV001Context();

    /// <summary>
    /// Constructor - setup for DI
    /// </summary>
    /// <param name="contentTypeRepository"></param>
    public ContentTypesController(IRepository<ContentType> repository)
    {
        _repository = repository;
    }

    // GET odata/ContentTypes
    [Queryable]
    public virtual IEnumerable<ContentTypes> Get(ODataQueryOptions<ContentType> options)
    {
        // TODO:  Use try/catch or using / unitOfWOrk

        var userId = 102;   // mock
        var result = options.ApplyTo(_repository.Query().Get()
            .Where(u => u.UserId == userId)
            .OrderBy(o => o.Description)).Cast<ContentType>();

        var dto = Mapper.Map<IEnumerable<ContentType>,IEnumerable<ContentTypes>>(result); 

        return dto;
    }
}

Should I be using the UnitOfWork rather than the repository, and if so is the following a correct implementation?

using (var unitOfWork = new Repository.UnitOfWork(_db))
{
    var userId = 102;   // mock
    var result = options.ApplyTo(unitOfWork.Repository<ContentType>().Query().Get()
        .Where(u => u.UserId == userId)
        .OrderBy(o => o.Description)).Cast<ContentType>();

    var dto = Mapper.Map<IEnumerable<ContentType>, IEnumerable<ContentTypes>>(result);

    return dto;
}

Somehow I think this circumvents the whole DI thing - suggestions welcome.

-- UPDATE --

Here is the same code using the DF database context:

        using (var u = new ProjectV001Context())
        {
            var result = from contentTypes in u.ContentTypes
                         where contentTypes.UserId == userId
                         orderby contentTypes.Description
                         select contentTypes;
        }

There have been other discussions (and here) about whether or not to further abstract EF's db context, and as @qujck points out,

...having your own abstraction for UnitOfWork and Repository gives you maximum control and flexibility when mocking your unit tests.

All very well, but for me, the real power of these abstractions is they provide a simple way to apply Aspect Oriented Programming techniques and adhere to the SOLID principles.

I have reworded the question to include the initial intent: In the first sample, I am using a generic repository, creating a specific repository for each type, in this case, ContentTypes.

So just accepting that I am using the generic framework... Looking at the bootstrap setup:

        builder.RegisterType<Repository<ContentType>>().As<IRepository<ContentType>>().InstancePerHttpRequest();

    builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerHttpRequest();

    builder.RegisterType<ContentTypesController>().As<IContentTypesController>().InstancePerHttpRequest();

If I used the generic repository, I would have to register a separate repository for each type, rather than just one registration for the UnitOfWork (seems more efficient).

My idea for an initial setup for using the UnitOfWork is as follows:

    private readonly IUnitOfWork _uow;

    public ContentTypesController(IUnitOfWork unitOfWork)
    {
        _uow = unitOfWork;
    }

Implementation:

        try
        {
            var result = options.ApplyTo(_uow.Repository<ContentType>().Query().Get()
                .Where(u => u.UserId == userId)
                .OrderBy(o => o.Description)).Cast<ContentType>();

            IQueryable<ContentTypes> dto = result.Project().To<ContentTypes>();

            return dto;
        }
        catch (Exception ex)
        {
            throw ex;
        }

In this case, I'm not using a using() statement, as when I do I get an error 500. What I'm finding is that the Dispose method is being called twice:

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            _db.Dispose();
        }
        base.Dispose(disposing);
    }

Is this implementation correct (should I be using the Repository rather than uow), and is it best to use the UnitOfWork or Repository implementation, and how do ensure I'm using my DI framework with this UnitOfWork implementation?

Community
  • 1
  • 1
ElHaix
  • 12,846
  • 27
  • 115
  • 203
  • http://stackoverflow.com/a/21584605/304832 – danludwig Feb 08 '14 at 23:04
  • Your controller should get the uow via the constructor. What is your problem with this? – Wiktor Zychla Feb 09 '14 at 17:41
  • @WiktorZychla - I forgot to add the implementation - it's there now. – ElHaix Feb 09 '14 at 23:02
  • Personally I would argue against adding layer upon layer upon layer like this. Unnecessary complication is one of the great evils of coding, easy to talk yourself into it but makes for a real pain to get actual work done. EF is all about making it easier and your code cleaner, while still giving you as much flexibility as possible. – Timothy Walters Feb 10 '14 at 01:47
  • @ElHaix: this looks ok. If your unit of work is injected, then you **don't have to dispose it in the constructor** as the disposal will be done outside, at the end of the request pipeline. – Wiktor Zychla Feb 10 '14 at 13:06
  • @TimothyWalters And I would argu that data centric apps can greatly benefit from a unified business layer and logic. A proper implemented Repository and UnitOfWork pattern should not add complexity to anything beside creating a new table, which is a 5 min task to begin with. But forgetting a data operation on creation or update of an entity because of the lack of a business layer can be very costy in both troubleshooting and data corruption if pushed on live environment. In any application that has a different main focus, then yes, I would agree that EF itself is a good enough DAL+Domain combo – Pluc Oct 07 '14 at 11:18

0 Answers0