h b*_*bob 3 c# entity-framework automapper asp.net-web-api
我读过的大部分内容(例如来自作者的内容)都表明应该使用 AutoMapper 将实体映射到 DTO。它不应该从数据库加载任何内容。
但如果我有这个怎么办:
public class Customer {
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Order> Orders { get; set; }
}
public class CustomerDto {
public int Id { get; set; }
public string Name { get; set; }
public IEnumerable<int> OrderIds { get; set; } // here is the problem
}
Run Code Online (Sandbox Code Playgroud)
我需要从 DTO 映射到实体(即从CustomerDto到Customer),但首先我必须使用该外键列表从数据库加载相应的实体。AutoMapper 可以使用自定义转换器来做到这一点。
我同意这感觉不对……但是还有什么选择呢?将该逻辑粘贴到控制器、服务、存储库、某些管理器类中?所有这些似乎都在将逻辑推向同一层的其他地方。如果我这样做,我还必须手动执行映射!
从 DDD 的角度来看,DTO 不应该是域的一部分。因此 AutoMapper 也不是域的一部分,因为它知道 DTO。所以 AutoMapper 与控制器、服务等处于同一层。
那么,将 DTO 到实体的逻辑(包括访问数据库,并可能抛出异常)放入 AutoMapper 映射中是否有意义?
编辑
@ChrisSimon 下面的精彩答案从 DDD 的角度解释了为什么我不应该这样做。从非 DDD 的角度来看,是否有令人信服的理由不使用 AutoMapper 从数据库加载?
首先,我将总结一下我对 DDD 中实体的理解:
使用 Automapper 从 Dto 转换为实体意味着实体放弃其状态的所有权。如果 dto 处于无效状态,而您将其直接映射到实体上,则该实体最终可能会处于无效状态 - 您已经失去了使实体包含数据 + 逻辑的价值,而这是 DDD 实体的基础。
为了就如何解决这个问题提出建议,我会问 - 您想要实现的操作是什么?DDD 鼓励我们不要考虑 CRUD 操作,而是考虑真实的业务流程,并在我们的实体上对它们进行建模。在本例中,您似乎将订单链接到客户实体。
在应用程序服务中,我会有一个类似的方法:
void LinkOrdersToCustomer(CustomerDto dto)
{
using (var dbTxn = _txnFactory.NewTransaction())
{
var customer = _customerRepository.Get(dto.Id);
foreach (var orderId in dto.OrderIds)
{
var order = _orderRepository.Get(orderId);
customer.LinkToOrder(order);
}
dbTxn.Save();
}
}
Run Code Online (Sandbox Code Playgroud)
在 LinkToOrder 方法中,我将具有执行以下操作的显式逻辑:
只有这样我才会将其添加到客户订单的集合中。
这样,应用程序“流”和基础设施管理包含在应用程序/服务层中,但真正的业务逻辑包含在域层中 - 在您的实体中。
如果上述要求与您的申请不相关,您可能还有其他要求。如果没有,那么也许没有必要走 DDD 的路——虽然 DDD 有很多东西需要添加,但它的开销通常只有在具有大量复杂业务逻辑的系统中才值得。
这与您提出的问题无关,但我还建议您看一下客户和订单的建模。它们都是独立的聚合吗?如果是这样,将 Customer 建模为包含 Order 集合可能会导致出现问题 - 当客户拥有一百万个订单时会发生什么?即使集合是延迟加载的,您也知道在某些时候会尝试加载它,并且您的性能会受到影响。这里有一些关于聚合设计的好读物:http://dddcommunity.org/library/vernon_2011/,它建议通过 Id 而不是参考来建模参考。在您的情况下,您可能有一个 OrderId 集合,甚至可能有一个全新的实体来表示链接 -CustomerOrderLink它有两个属性 - CustomerId 和 OrderId。那么您的任何实体都不会嵌入集合。
| 归档时间: |
|
| 查看次数: |
3258 次 |
| 最近记录: |