【问题标题】:Object mapper vs Object wrapper对象映射器与对象包装器
【发布时间】:2017-07-02 21:10:29
【问题描述】:

我希望能得到一点帮助...

假设在一个应用程序中,我们有一个数据层和一个业务逻辑层。在 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 */ 部分。我们团队中有一个关于如何进行“映射”的讨论。

一种方法是使用自动映射器或手动映射器。 第二种方法是使用类似于 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 的引用),但我不确定。

使用一种方法比另一种方法有什么优点/缺点吗?

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

【问题讨论】:

  • 如果您打算使用包装器方法,您不妨只使用实体而忘记使用 dto 对象。您没有购买任何使用包装器的东西,而是添加了紧密耦合和另一个依赖项。
  • @dbugger - 谢谢你的回答。你是指哪个依赖?无论我们使用映射器还是包装器来创建 DTO,BLL 都会始终知道来自 DAL 的接口。

标签: oop automapper data-access-layer objectmapper


【解决方案1】:

您没有提到您的“轻量级 ORM”。我分两部分回答。

如果您使用创建代理的 ORM

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

在 DTO 中包装实体将一无所获。您仍然在访问实体。

使用 DTO 并使用 AutoMapper 之类的映射工具进行映射是很好的解决方案。

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

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

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

请参阅this 问题。有点不同;我在问是/否,而你在问如何。但它仍然会帮助你。

【讨论】:

  • 谢谢 A_J。花了一些时间来解决讨论,但是您在 ORM 有代理和没有代理之间所做的区分对我们很有帮助。在我们的例子中,ORM 没有生成代理,但实体需要特殊属性才能让 ORM 映射它们。由于我们不想在其他层中公开此属性,因此我们最终将它们包装在 DTO 中并使用自动映射器。
【解决方案2】:

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

而且,事实上,您和您的团队应该使用 AutoMapper 而不是重复相同的代码吨次,其中包括将某些属性从 A 设置为 B、A 到 C、C 到 B。 ..

【讨论】:

  • 事实上,对我来说,在大型代码库中手动映射可能只是proud developer 综合症的症状!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-14
  • 2017-10-30
  • 1970-01-01
  • 1970-01-01
  • 2016-12-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多