对象映射器与对象包装器

Object mapper vs Object wrapper

如果能给我一点帮助,我将不胜感激...

假设在一个应用程序中我们有一个数据层和一个业务逻辑层。在 DAL 中,我们有以下实体:

public class Customer {
    public string Name {get; set;}
    public ICollection<Address> Addresses {get; set;}
}

public class Address {
    public string Street {get; set;}
}

在 BLL 中,我们有以下 POCO:

public class CustomerDto {
    public string Name {get; set;}
    public ICollection<AddressDto> Addresses {get; set;}
}

public class AddressDto {
    public string Street {get; set;}
}

DAL 中的实体使用轻量级 ORM 填充,并使用存储库从 BLL 中检索。例如:

public class CustomerInformationService {

    private readonly ICustomerRepository _repository {get; set;}
    public CustomerInformationService (ICustomerRepository repository)
    {
         _repository = repository;
    }
    public class CustomerDto Get(int id)
    {
         var customerEntity = _repository.Get(id);

         var customerDto = /* SOME TRANSFORMATION HERE */

         return customerDTO;
    }
}

我的问题是关于 /* SOME TRANSFORMATION HERE */ 部分。我们的团队正在讨论如何执行 "mapping"。

一种方法是使用自动映射器或手动映射器。 第二种方法是使用类似于 Entity 的包装器并引用 DTO 以保存对象之间的复制操作。像这样:

public class CustomerDto
{
     private IEntity _customerEntity;

     public IEntity CustomerEntity { get {return _customerEntity;}}

     public CustomerDto(IEntity customerEntity)
     {
          _customerEntity = customerEntity;
     }

     public string Name 
     { 
          get { return _customerEntity.Name; }
     }
     public ICollection<Address> Addresses 
     { 
          get { return _customerEntity.Addresses; }
     }
}

我觉得第二种方法有点奇怪,因为 _customerEntity.Addresses 感觉像是我的 DAL 和 BLL 之间的泄漏(_customerEntity 的参考),但我不确定。

有没有advantages/disavantages使用一种方法而不是另一种方法?

附加信息:我们通常拉一个最大值。一次需要在实体和 DTO 之间转换的 1000 条记录。

我打赌服务层方法。基本上是因为看起来像业务对象或 域对象 的东西与 DTOs.

无关

而且,事实上,您和您的团队应该使用 AutoMapper 而不是多次重复相同的代码,这包括将一些属性从 A 设置到 B,从 A 到 C , C 到 B...

您没有提到您的“ligth-weight ORM”。我分两部分回答。

如果您使用的是创建代理的 ORM

您应该避免将实体暴露在特定边界之外。像 NHibernate/EF 这样的 ORM 实现了基于代理的延迟加载。如果您将实体暴露给 application/UI 层,您将无法控制 ORM 行为。这可能会导致很多意想不到的问题,调试起来也会很困难。

在 DTO 中包装实体将一无所获。无论如何,您正在访问实体。

使用 DTO 并使用 AutoMapper 等映射器工具映射它们是很好的解决方案。

如果您使用的是不创建代理的 ORM

不要使用 DTO,直接使用您的实体。在许多情况下,DTO 在此处很有用并推荐使用。但是你给出的例子根本不需要DTO。

如果您选择使用 DTO,将实体包装在 DTO 中是没有意义的。如果无论如何都要使用 Entity,为什么要包装它?同样,像 AutoMapper 这样的工具可以提供帮助。

参考this问题。有点不同;我在问 Yes/No 而你在问 How。但它仍然会帮助你。