如何将DTO与EF,Autofac和通用数据存储库一起使用? [英] How do I use DTO's with EF, Autofac, and a generic data repository?

查看:121
本文介绍了如何将DTO与EF,Autofac和通用数据存储库一起使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我如何在EF,Autofac和通用数据存储库中使用DTO?

How do I use DTO's with EF, Autofac, and a generic data repository?

我正在建立一个新项目并已配置好我的DI / IoC(Autofac)使用通用存储库通过EF进行数据访问,并创建了OData服务端点 ContentTypesController

I'm in the process of setting up a new project and have configured my DI/IoC (Autofac), using a generic repository for data access through EF, and created an OData service endpoint, ContentTypesController.

这是控制器的顶部:

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类,其中包含不需要客户端查看/使用的字段-即。用户身份。在插入或更新方法时,将务实地设置此字段的值。

ContentType is the EF class in Project.DAL.Data.Models, which contains fields that do not need to be seen/used by the client - ie. UserId. In inserting or updating methods, the value of this field will be set pragmatically.

我的DTO位于Project.Core.ContentTypes中。

My DTO is located in Project.Core.ContentTypes.

1)我在这里正确使用工作单元模式吗?

1) Am I using the unit of work pattern here correctly?

2)我希望我的方法返回DTO,而不是所有实际实体对象的字段。我该如何设置?

2) I want my methods to return the DTO, and not all the fields from the actual entity object. How do I set this up?

-更新-

在以前的项目(以及不同的存储库),我正在按以下方式实现UoW:

In a previous project (and different repository) I was implementing the UoW as follows:

公共类ContentTypesController:ODataController
{
private ProjectDbContext _db = new ProjectDbContext();

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


推荐答案

嗯,您实际上不是使用UnitOfWork模式;只是通用存储库模式。至于返回的DTO,请查看Factory模式(为此我使用AutoMapper)。您可以创建dto并将automapper用作工厂以获取实体并转换为dto,或者将dtos转换为实体。配置AutoMapper非常简单,如下所示:

Well you're not actually using the UnitOfWork pattern; just the generic repository pattern. As for returning DTOs, look into the Factory pattern (I use AutoMapper for this). You can create your dtos and use automapper as a factory to take your entities and convert to dtos or your dtos and convert to entities. Configuring AutoMapper is pretty simple and looks like:

Mapper.CreateMap<ContentType, ContentTypeDto>();

并实际将ContentType映射到ContentTypeDto(假设您的属性名称匹配):

And to actually map a ContentType to ContentTypeDto (assuming your property names match):

var dto = Mapper.Map<ContentType, ContentTypeDto>(contentTypeEntity);

至于工作单元:不使用一个没有什么错,除非您计划换出ORM某个时候但是,如果您愿意,它非常简单:

As for unit of work: there's nothing wrong with not using one unless you plan on swapping out your ORM sometime. But if you do want it, it's pretty simple:

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

IUnitOfWork implements IDisposable and defines GetRepository() and SaveChanges().

您还必须创建仅定义Set,SaveChanges()的IDbContext。 ,并实现IDisposable。

You'll also have to create IDbContext which just defines Set, SaveChanges(), and implements IDisposable.

然后,您可以将IUnitOfWork注入控制器中,并使用GetRepository()来为控制器检索正确的存储库。这样,所有存储库共享1个单一上下文。

Then you can inject IUnitOfWork into your controller and use GetRepository() to retrieve the correct repository for your controller. This way, all repositories share 1 single context.

实现通用存储库和工作单元类示例位于此页面的下半部分。唯一的区别是它们的UnitOfWork不是通用的,但我在上面向您展示了。

编辑:我只是注意到您从存储库中获得了UnitOfWork:

I just noticed you're getting a UnitOfWork from your repository:

var unitOfWork = new Repository.UnitOfWork(_db);
var result = unitOfWork.Repository<ContentType>()...

我是不知道这是怎么回事。您的UnitOfWork应该放出您的存储库,但是看来您的存储库正在为您提供工作单元,然后您的UnitOfWork正在为您提供存储库?您介意共享您的存储库吗?我相信要正确实现UnitOfWork,您需要编辑存储库。

I'm not sure what's going on here. Your UnitOfWork should be dishing out your repositories but it seems like your repository is giving you your unit of work, and then your UnitOfWork is giving you back a repository? Would you mind sharing your repository? I believe to correctly implement UnitOfWork, you'll need to edit your repository.

这篇关于如何将DTO与EF,Autofac和通用数据存储库一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆