通用存储库或工作单元的正确实现是什么,哪些应该与EF一起使用?

时间:2014-02-08 23:02:26

标签: c# generics repository-pattern entity-framework-6 unit-of-work

我已经实现了通用RepositoryUnitOfWork找到了here

我的服务器端堆栈是:C#.Net 4.5,EF6,AutoMapper(适用于EF型号/ DTO),Autofac(DI),WebAPI,OData。

我的DI设置如下:

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();

这是我的OData控制器:

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;
    }
}

我是否应该使用UnitOfWork而不是存储库,如果是,那么以下是正确的实现吗?

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;
}

不知何故,我认为这会绕过整个DI事件 - 欢迎提出建议。

- 更新 -

以下是使用DF数据库上下文的相同代码:

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

关于是否进一步抽象EF的db上下文已经other discussions (and here),并且正如@qujck指出的那样,

  

...拥有自己的UnitOfWork和Repository抽象功能   模拟单元测试时的最大控制和灵活性。

     

一切都很好,但对我来说,这些抽象的真正力量是   它们提供了一种应用面向方面编程的简单方法   技术并遵守SOLID原则。

我重写了问题以包含初始意图:在第一个示例中,我使用的是通用存储库,为每种类型创建一个特定的存储库,在本例中为ContentTypes

所以只是接受我正在使用通用框架......看看bootstrap设置:

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

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

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

如果我使用通用存储库,我必须为每种类型注册一个单独的存储库,而不是只为UnitOfWork注册一个(似乎更有效)。

我对使用UnitOfWork进行初始设置的想法如下:

    private readonly IUnitOfWork _uow;

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

实现:

        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;
        }

在这种情况下,我没有使用using()语句,因为当我这样做时出现错误500.我发现的是Dispose方法被调用两次:< / p>

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

此实施是否正确(我应该使用Repository而不是uow),最好是使用UnitOfWorkRepository实施,以及如何使用确保我在这个UnitOfWork实现中使用我的DI框架?

0 个答案:

没有答案