假设您有一个订单作为聚合根。订单包含一个或多个订单项。
据我了解,存储库负责在被询问时实例化订单对象。
可以在创建订单对象时加载订单项(急切加载),也可以在客户端代码(延迟加载)访问订单项集时填充这些订单项。
如果我们使用预先加载,似乎存储库代码将负责在创建订单时保护订单项。
但是,如果我们使用延迟加载,那么在访问LineItems集合时如何调用存储库而不从订单域类创建对存储库的依赖?
答案 0 :(得分:2)
主要问题在于Repository
能够获得仅聚合根(呈现聚合),因此您无法使用Repository
来获取订单项。这可能导致聚合封装违规。
我提出的建议如下:
//Domain level:
public interface IOrderItemList {
IEnumerable<OrderItem> GetItems();
}
public class Order {
private IOrderItemList _orderItems;
public IEnumerable<OrderItem> OrderItems
{ get { return _orderItems.GetItems() } };
public Order(IOrderItemList orderItems)
{
_orderItems = orderItems;
}
}
public class OrderItemList : IOrderItemList
{
private IList<OrderItem> _orderItems;
public IEnumerable<OrderItem> GetItems() {
return _orderItems; //or another logic
}
//other implementation details
}
//Data level
public class OrderItemListProxy : IOrderItemList
{
//link to 'real' object
private OrderItemList _orderItemList;
private int _orderId;
//alternatively:
//private OrderEntity _orderEntity;
//ORM context
private DbContext _context;
public OrderItemListProxy(int orderId, DbContext context)
{
_orderId = orderId;
_context = context;
}
public IEnumerable<OrderItem> GetItems() {
if (_orderItemList == null)
{
var orderItemEntities = DbContext.Orders
.Single(order => order.Id == _orderId).OrderItems;
var orderItems = orderItemEntites.Select(...);
//alternatively: use factory to create OrderItem from OrderItemEntity
_orderItemList = new OrderItemList(orderItems);
}
return _orderItemList.GetItems();
}
}
public class OrderRepository
{
//ORM context
private DbContext _context;
Order GetOrder(int id)
{
var orderEntity = _context.Single(order => order.Id == id);
var order = new Order(new OrderItemListProxy(id, _context))
//alternatively:
//var order = new Order(new OrderItemListProxy(orderEntity, _context))
...
//init other fields
...
}
//other methods
...
}
最重要的是,IOrderItemList
对应于域层,但OrderItemListProxy
对应于数据层。
最后,
IList<OrderItem>
代替自定义IOrderItemList
或其他适当的界面。