使用DTO传输服务层和UI层之间的数据 [英] Using DTO to transfer data between service layer and UI layer

查看:1166
本文介绍了使用DTO传输服务层和UI层之间的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在试图算出这个数天,但似乎有与ASP.NET MVC这一特定主题很少的信息。我一直在周围的Googling了几天,都没有真正能够计算出任何关于这一具体问题。

I've been trying to figure this out for days but there seems to be very little info on this particular subject with ASP.NET MVC. I've been Googling around for days and haven't really been able to figure anything out about this particular issue.

我有一个3层的项目。商务,DAL和UI /网络层。在DAL是的DbContext,资料库和工作单位。在业务层领域层的所有接口和EF车型。在业务层也有与DTO的为EF模型和访问资源库中的通用信息库服务的服务层。 <一href=\"http://lh5.ggpht.com/_XHclJS9Jxg0/TKzwre5rfbI/AAAAAAAAALA/VoTXLxXS5pY/s1600-h/Drawing1%5B4%5D.jpg\">This图片应该有助于解释。

I've got a 3 layer project. Business, DAL and UI/Web layer. In the DAL is dbcontext, repository and unit of work. In the business layer is a domain layer with all the interfaces and the EF models. In the business layer there is also a service layer with DTOs for the EF models and a generic repository service that accesses the repository. This picture should help explain it.

我的问题是,我似乎无法弄清楚如何使用的DTO将数据从业务层传送。

My problem is that i just can't seem to figure out how to use the DTOs to transfer data from the business layer.

我已经创建服务类的DTO的。我已经得到了像一个锚和ImageDTO模型和相同的。我会为每个DTO服务类。所以,我有一个形象的服务和锚服务。这些服务继承了存储库服务,并在此刻实现自己的服务。但多数民众赞成有关,据我已经得到了。由于这些服务有通过国际奥委会收到IUnitOfWork接口的构造我pretty多得搁浅。

I've created service classes for the DTOs. I've got a ImageDTO and model and same for image anchors. I've created a service class for each DTO. So i've got a image service and anchor service. These services inherit the repository service and at the moment implement their own services. But thats about as far as i have gotten. Since these services have constructors that receive a IUnitOfWork interface via IoC i've pretty much gotten stranded.

如果我直接从UI引用的一切服务工作,因为它应该,但我只是不能让我围绕着如何使用DTO的传输数据无论从业务层到UI层和周围的其他方式的想法。

If i reference the service directly from the UI everything works as it should but i just can't get my mind around how to use DTOs to transmit data both from the service layer to the UI layer and the other way around.

我的服务层:

业务/服务/ DTO的

Business/Services/DTOs

public class AnchorDto
{
      public int Id { get; set; }
      public int x1 { get; set; }
      public int y1 { get; set; }
      public int x2 { get; set; }
      public int y2 { get; set; }
      public string description { get; set; }
      public int  imageId { get; set; }
      public int targetImageId { get; set; }

      public AnchorDto(int Id, int x1, int y1, int x2, int y2, string description, int imageId, int targetImageId)
      {
          // Just mapping input to the DTO 
      }
}

public class ImageDto
{
    public int Id { get; set; }
    public string name { get; set; }
    public string title { get; set; }
    public string description { get; set; }
    public virtual IList<AnchorDto> anchors { get; set; }

    public ImageDto(int Id, string name, string title, string description, IList<AnchorDto> anchors )
    {
        // Just mapping input to DTO
    }
}

业务/服务/服务

Business/Services/Services

public class RepoService<TEntity> : IRepoService<TEntity> where TEntity : class
{
    private IRepository<TEntity> repo;

    public RepoService(IUnitOfWork repo)
    {
        this.repo = repo.GetRepository<TEntity>();
    }

    public IEnumerable<TEntity> Get(
        Expression<Func<TEntity, bool>> filter = null,
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
        string includeProperties = "")
        {
            return repo.Get(filter, orderBy, includeProperties);
        }

        public TEntity GetByID(object id)
        {
            return repo.GetByID(id);
        }

        public void Insert(TEntity entity)
        {
            repo.Insert(entity);
        }

        public void Delete(object id)
        {
            repo.Delete(id);
        }

        public void Delete(TEntity entityToDelete)
        {
            repo.Delete(entityToDelete);
        }

        public void Update(TEntity entityToUpdate)
        {
            repo.Update(entityToUpdate);
        }
    }

图片服务时,IImageService接口目前是空的,直到我找出我需要实现。

The Image Service, the IImageService interface is currently empty until i figure out what i need to implement.

public class ImageService : RepoService<ImageModel>, IImageService
{
    public ImageService(IUnitOfWork repo)
        : base(repo)
    {

    }
}

目前我的控制器是不是真的工作,未使用的服务层,所以我决定不包括任何的。我打算一旦我整理这个问题出到DTO的使用自动映射器的ViewModels映射。

At the moment my controllers aren't really working and aren't using the service layer so i decided not to include any of those. I plan to map the DTOs to ViewModels using auto mapper once i've sorted this issue out.

所以,现在,任何人都请足够的知识给我这个想法,我缺少的,这样我可以算出来?

So now, please anyone knowledgeable enough to give me that idea I'm missing so that i can figure this out?

推荐答案

您的服务应该得到的DTO,它们映射到业务实体,并将它们发送到存储库。还应该从资源库中检索业务实体,它们映射到DTO的,返回的DTO的作为反应变量。所以,你的业务实体从来没有从业务层全身而退,只有做的DTO

Your service should receive DTOs, map them to business entities and send them to the repository. It should also retrieve business entities from the repository, map them to DTOs and return the DTOs as reponses. So your business entities never get out from the business layer, only the DTOs do.

那么你的UI \\ Weblayer应该是不知道的实体企业。该Web层应只了解的DTO。为了执行这个规则是非常重要的,你的UI层不使用该服务实现类(这应该是私有的),只是接口。和服务接口shouldn't依赖于商业实体,只是DTO的。

Then your UI\Weblayer should be unaware of the business entities. The web layer should only know about the DTOs. To enforce this rule is very important that your UI layer does not uses the service implementation classes (which should be private), just the interfaces. And the service interfaces shouldn´t depend on the business entities, just the DTOs.

所以,你需要根据的DTO服务接口,和你的基本服务类的需求为DTO的另一个一般的参数。我喜欢有实体​​和DTO的基类,使他们可以声明为:

So you need service interfaces based on DTOs, and your base service class needs another generic argument for the DTO. I like to have a base class for entities and DTOs so they can be declared as:

//Your UI\presentation layer will work with the interfaces (The inheriting ones) 
//so it is very important that there is no dependency
//on the business entities in the interface, just on the DTOs!
protected interface IRepoService<TDto> 
    where TDto: DTOBase
{
    //I'm just adding a couple of methods  but you get the idea
    TDto GetByID(object id);
    void Update(TDto entityToUpdateDto)
}

//This is the interface that will be used by your UI layer
public IImageService: IRepoService<ImageDTO>
{
}

//This class and the ones inheriting should never be used by your 
//presentation\UI layer because they depend on the business entities!
//(And it is a best practice to depend on interfaces, anyway)
protected abstract class RepoService<TEntity, TDto> : IRepoService<TDto> 
    where TEntity : EntityBase
    where TDto: DTOBase
{
    ... 
}

//This class should never be used by your service layer. 
//Your UI layer should always use IImageService
//You could have a different namespace like Service.Implementation and make sure
//it is not included by your UI layer
public class ImageService : RepoService<ImageModel, ImageDto>, IImageService
{
    ...
}

然后,您需要添加实体和DTO到基本服务之间的映射关系,而不实际执行的映射(因为这取决于每个具体的实体和DTO类)的一种方式。你可以宣布执行映射,将需要对每个具体的服务实现(如 ImageService )的抽象方法。基地RepoService的implemantion看起来像:

You then need a way of adding the mapping between entities and DTO to that base service without actually implementing the mapping (as it depends on each concrete entity and DTO classes). You could declare abstract methods that perform the mapping and will need to be implemented on each specific service (like ImageService). The implemantion of the base RepoService would look like:

public TDto GetByID(object id)
{
    //I'm writing it this way so its clear what the method is doing
    var entity = repo.GetByID(id);
    var dto = this.EntityToDto(entity);
    return dto;
}

public void Update(TDto entityToUpdateDto)
{
    var entity = this.DtoToEntity(entityToUpdateDto)
    repo.Update(entity);
}

//These methods will need to be implemented by every service like ImageService
protected abstract TEntity DtoToEntity(TDto dto);
protected abstract TDto EntityToDto(TEntity entity);

或者,你可以声明地图服务,添加依赖与应该由你的IOC(这使得更多的意义,如果你需要在不同的服务相同的映射)来提供一个appropiated地图服务。 RepoService的实施将是这样的:

Or you could declare mapping services, adding a dependency with an appropiated mapping service that should be provided by your IOC (This makes more sense if you need the same mapping on different services). The implementation of RepoService would look like:

private IRepository<TEntity> _repo;
private IDtoMappingService<TEntity, TDto> _mappingService;

public RepoService(IUnitOfWork repo, IDtoMappingService<TEntity, TDto> mapping)
{
    _repo = repo.GetRepository<TEntity>();
    _mappingService = mapping;
}

public TDto GetByID(object id)
{
    //I'm writing it this way so its clear what the method is doing
    var entity = repo.GetByID(id);
    var dto = _mappingService.EntityToDto(entity);
    return dto;
}

public void Update(TDto entityToUpdateDto)
{
    var entity = _mappingService.DtoToEntity(entityToUpdateDto)
    repo.Update(entity);
}

//You will need to create implementations of this interface for each 
//TEntity-TDto combination
//Then include them in your dependency injection configuration
public interface IDtoMappingService<TEntity, TDto>
    where TEntity : EntityBase
    where TDto: DTOBase
{
    public TEntity DtoToEntity(TDto dto);
    public TDto EntityToDto(TEntity entity);
}

在这两种情况下(抽象方法或地图服务),您可以手动或使用如工具实现实体和DTO的之间的映射Automapper 。但是,你应该使用AutoMapper和实体框架的时候,虽然那是另一个话题很小心! (谷歌一些有关这个并加载数据时收集关于该主题的一些信息。作为第一个建议要注意查询对数据库中执行,所以你必须比负载鸵鸟政策或多个发送许多查询。保存数据时要注意到你的收藏和关系)

In both cases (abstract methods or mapping services), you can implement the mapping between the entities and DTOs manually or using a tool like Automapper. But you should be very careful when using the AutoMapper and entity framework, although that is another topic! (Google a bit about that and collect some information on the topic. As a first advice pay attention to the queries being executed against the database when loading data so you don´t load more than needed or send many queries. When saving data pay attention to your collections and relationships)

龙后也许吧,但我希望它能帮助!

Long post maybe, but I hope it helps!

这篇关于使用DTO传输服务层和UI层之间的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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