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?