首先,您应该将领域概念与实现细节分开。聚合模式是关于如何组织你的域,而延迟加载是一个实现细节。
另外,我不同意@Eben Roux 关于协议不一致的观点。在我看来,延迟加载并不矛盾。我说明原因。
延迟加载自身
要了解如何实现延迟加载,您可以参考 Martin Fowler 的 PoEAAA 模式 'Lazy loading'。对我来说,代理模式是最好的解决方案。
此外,重要的是现在大多数 ORM 支持延迟加载,但对于数据模型(而不是域模型)。
将数据模型和域模型分开并使用存储库来隐藏这种转换是一种很好的做法:
分离的域和数据模型
在这种情况下,域模型的对象是在隐藏 ORM 上下文的存储库中构建的。需要的数据对象和所有的关联由ORM加载,然后转换为领域模型,最后返回构造好的领域对象。
问题是如何在域对象的创建过程中而不是在它的生命周期中加载一些关联。您可以在实体内部使用 Repoisotry,我认为它没有任何问题。它看起来像:
public class Post {
private ICommentsRepository _commentsRepository;
private IList<Comments> _comments;
//necessary to perform lazy loading (repository always wroks with ids)
private IList<int> _commentIds;
//realize lazy loading
...
}
有问题:
- 您的模型现在变得不清楚。它包含“技术”信息,例如
_commentIds。
- 只要您想定义
ICommentsRepository,您就可以将Comment 声明为聚合根。如果我们将聚合模式引入域模型,则应该为聚合根创建存储库。因此这意味着Comment 和Post 是不同的聚合根。并且可能不是您想要的。
有更好的解决方案:
public interface ICommentList {
...
}
public class CommentList : ICommentList {
...
}
public class CommentListProxy : ICommentList {
private CommentList _realCommentList;
private IList<int> _commentIds;
//realize lazy loading here using ORMs capabilities!
//don't use repository here!
}
public class Post {
private ICommentList _commentList;
...
}
后存储库将使用代理对象初始化_commentList 字段。另外,有必要说:
-
CommentListProxy 与数据模型层有关,与域模型无关。它使用 ORM 功能来实现延迟加载
- 因此不使用存储库,因此您可以将
CommentList 视为Post 聚合的一部分。
这种方法唯一可能的缺点是在使用域对象操作时会进行隐式数据库查询。 Post 类的用户必须清楚这一点。
智能 ORM
最后有一种 ORM 允许您对域和数据使用相同的模型。它以与数据模型相同的方式实现域模型的延迟加载。看看 DataObjects.Net。在某些情况下,这是一个很好的解决方案。