如何让实体延迟加载它的关系?
例如:帖子和评论模型,其中帖子可以有0个或更多评论。如何使post实体延迟的getComments()方法加载其注释?
我的第一个想法是,将一个CommentRepository注入我的Post实体,这有什么不好?由于实体和存储库是may域的一部分,为什么它们不能彼此具有双向知识?
谢谢
更新
我知道有很多优秀的行业标准ORM可以为主要语言执行延迟加载,但我不想依赖它的魔法。我正在寻找一个ORM / DBAL不可知解决方案来确保应用程序的低耦合。
答案 0 :(得分:2)
聚合表示一致性边界,因此永远不需要延迟加载相关数据,因为整体聚合始终是一致的。属于聚合的所有对象都不需要自己存在。如果你确实有一个具有自己生命周期的对象,那么它需要从聚合中删除。
如果您确实发现需要这样做,可能需要重新考虑您的设计。可能是您正在使用对象模型进行查询。您应该使用可以执行此功能的轻量级查询模型。
将存储库或服务注入实体通常不是最好的主意。应该首选双重调度机制。
但在你的情况下,我仍然会尝试不延迟加载。
答案 1 :(得分:1)
考虑使用子类Post的代理,覆盖getComments()
方法。使用CommentRepository注入代理,并在重写的getComment()
方法中访问它。
这就是ORM通常会这样做的方式。它使您的域类保持干净,因为只有代理依赖于数据访问机制。
答案 2 :(得分:0)
首先,您应该将域概念与实现细节分开。 Agreagate模式是关于如何组织您的域,延迟加载是一个实现细节。
另外,我不同意@Eben Roux关于agreates的不一致性。懒惰装载在我看来并不矛盾。我表达了原因。
要了解如何实现延迟加载,您可以参考Martin Fowler的PoEAAA
模式'Lazy loading'
。对我来说,代理模式是最好的解决方案。
此外,重要的是现在大多数ORM支持延迟加载,但是对于数据模型(不是域模型)。
将数据模型和域模型分开并使用repostiories隐藏此转换是一种很好的做法:
在这种情况下,域模型的对象在存储库中构建,这些对象隐藏了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
是聚合根。如果我们将agregate模式引入到域模型中,那么应该仅为了agregate根而创建存储库。因此,这意味着Comment
和Post
是不同的agregate根。可能它不是你想要的。有更好的解决方案:
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
agregate的一部分。此方法唯一可能的缺点是在使用域对象进行隐式数据库查询时。 Post
类的用户必须清楚这一点。
最后有一些ORM允许您对域和数据使用相同的模型。它以与数据模型相同的方式实现域模型的延迟加载。看看DataObjects.Net。在某些情况下,这是一个很好的解决方案。