实体依赖于存储库抽象



如何使实体延迟加载其关系?

例如:文章和评论模型,其中一篇文章可以有0个或多个评论。如何使Post实体上的getComments()方法惰性地加载其Comments?

我的第一个想法是,在我的Post实体中注入一个CommentRepository,这怎么不好?既然实体和存储库是may域的一部分,为什么它们不能对彼此有双向的了解?

谢谢

更新
我知道有很多优秀的行业标准ORM为主要语言执行懒惰加载,但我不想依赖它的魔力。我正在寻找一个ORM/DBAL不可知的解决方案,以确保应用程序的低耦合性。

聚合表示一致性边界,因此永远不应该延迟加载相关数据,因为聚合作为一个整体应该始终是一致的。所有属于聚合的对象都不需要单独存在。如果你有一个有自己生命周期的对象,那么它需要从聚合中删除。

当你发现你需要这样做时,你可能需要重新思考你的设计。可能是您正在使用对象模型进行查询。您应该有一个可以执行此功能的轻量级查询模型。

将存储库或服务注入实体通常不是最好的主意。应首选双重调度机制。

但在你的情况下,我仍然会尝试而不是懒惰加载。

考虑使用一个代理,该代理子类化Post,覆盖getComments()方法。使用CommentRepository注入代理,并在重写的getComment()方法中访问它。

ORM通常就是这样做的。它保持域类的干净,因为只有代理依赖于数据访问机制。

首先,您应该将域概念与实现细节分开。Agreagate模式是关于如何组织您的域,而延迟加载是一个实现细节。

此外,我不同意@Eben Roux关于协议不一致的观点。在我看来,懒散的装载毫无矛盾。我表达原因。

懒加载本身

要了解延迟加载是如何实现的,可以参考MartinFowler的PoEAAA模式'Lazy loading'。对我来说,代理模式是最好的解决方案。此外,重要的是,目前大多数ORM都支持延迟加载,但支持数据模型(而不是域模型)。

将数据模型和域模型分离并使用repositories来隐藏这种转换是一种很好的做法:

分离的域和数据模型

在这种情况下,域模型的对象是在隐藏ORM上下文的存储库中构建的。ORM加载所需的数据对象和所有关联,然后执行到域模型的转换,最后返回构造的域对象。

问题是如何加载一些关联,而不是在域对象的创建过程中,而是在它的生命周期中。你可以在实体内部使用Repisotry,我认为它没有错。它看起来像:

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
    ...
}

存在问题:

  1. 您的模型现在变得不清晰。它包含像_commentIds这样的"技术"信息
  2. 只要您想定义ICommentsRepository,就可以将Comment声明为聚合根。如果我们在领域模型中引入agregate模式,那么应该只为agregate根创建存储库。说明CCD_ 8和CCD_。可能这不是你想要的

有更好的解决方案:

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字段。此外,有必要说:

  1. CommentListProxy与数据模型层有关,而与领域模型无关。它使用ORM的功能来实现延迟加载
  2. 因此不使用存储库,因此您可以将CommentList视为Post协议的一部分

这种方法唯一可能的缺点是在使用域对象操作时使用隐式数据库查询。这对于Post类的用户来说必须是清楚的。

智能ORM

最后还有一种ORM,它允许您对域和数据使用相同的模型。它以与数据模型相同的方式实现了域模型的延迟加载。看看DataObjects.Net。在某些情况下,它是一个很好的解决方案。

最新更新