如何将DTO与EF,Autofac和通用数据存储库一起使用?
我正在设置一个新项目并配置了我的DI / IoC(Autofac),使用通用存储库通过EF进行数据访问,并创建了一个OData服务端点ContentTypesController
。< / p>
这是控制器的顶部:
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 Task<IQueryable<ContentType>> Get(ODataQueryOptions<ContentType> options)
{
// mock
var userId = 102;
//var unitOfWork = new Repository.UnitOfWork(_db); <-- removed from the original question
var result = _repository.Query()
.Filter(u => u.UserId == userId)
.GetAsync();
return result;
}
ContentType
是Project.DAL.Data.Models中的EF类,它包含客户端不需要查看/使用的字段 - 即。用户身份。在插入或更新方法时,将以实际方式设置此字段的值。
我的DTO位于Project.Core.ContentTypes。
1)我是否正确使用了工作单元模式?
2)我希望我的方法返回DTO,而不是实际实体对象的所有字段。我该如何设置?
- 更新 -
在之前的项目(和不同的存储库)中,我按如下方式实现了UoW:
public class ContentTypesController:ODataController { private ProjectDbContext _db = new ProjectDbContext();
public IEnumerable<ContentType> Get(ODataQueryOptions<ContentType> options)
{
var unitOfWork = new Project.Repository.UnitOfWork(_db);
var contentTypes = options.ApplyTo(unitOfWork.Repository<ContentType>().Queryable
.OrderBy(c => c.Description))
.Cast<ContentType>().ToList();
unitOfWork.Save(); // includes Dispose()
return contentTypes;
}
答案 0 :(得分:2)
嗯,你实际上并没有使用UnitOfWork模式;只是通用的存储库模式。至于返回DTO,请查看Factory模式(我使用AutoMapper)。您可以创建您的dtos并使用automapper作为工厂来获取您的实体并转换为dtos或您的dtos并转换为实体。配置AutoMapper非常简单,如下所示:
Mapper.CreateMap<ContentType, ContentTypeDto>();
实际上将ContentType映射到ContentTypeDto(假设您的属性名称匹配):
var dto = Mapper.Map<ContentType, ContentTypeDto>(contentTypeEntity);
至于工作单元:除非你计划在某个时候更换你的ORM,否则没有使用它。但如果你真的想要它,那很简单:
public class UnitOfWork : IUnitOfWork
{
private readonly IDbContext _context;
private readonly Dictionary<Type, object> _repos;
public IRepository<T> GetRepository<T>() {
if (_repos.ContainsKey(typeof (T)))
return _repos[typeof (T)] as IRepository<T>;
var repo = new Repository(_context);
_repos.Add(typeof (T), repo);
return repo;
}
public int SaveChanges() {
return _context.SaveChanges();
}
dispose stuff - make sure to dispose your context
}
IUnitOfWork实现了IDisposable并定义了GetRepository()和SaveChanges()。
您还必须创建IDbContext,它只定义Set,SaveChanges(),并实现IDisposable。
然后,您可以将IUnitOfWork注入控制器并使用GetRepository()为您的控制器检索正确的存储库。这样,所有存储库共享1个单独的上下文。
编辑:我刚刚注意到你从你的存储库中获得了一个UnitOfWork:
var unitOfWork = new Repository.UnitOfWork(_db);
var result = unitOfWork.Repository<ContentType>()...
我不确定这里发生了什么。你的UnitOfWork应该放弃你的存储库,但看起来你的存储库给你的工作单元,然后你的UnitOfWork给你一个存储库?你介意分享你的存储库吗?我相信要正确实现UnitOfWork,您需要编辑您的存储库。