我已经实现了通用Repository
和UnitOfWork
找到了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
),最好是使用UnitOfWork
或Repository
实施,以及如何使用确保我在这个UnitOfWork
实现中使用我的DI框架?