实体取决于存储库抽象

时间:2014-09-01 22:43:18

标签: oop design-patterns domain-driven-design object-oriented-analysis

如何让实体延迟加载它的关系?

例如:帖子和评论模型,其中帖子可以有0个或更多评论。如何使post实体延迟的getComments()方法加载其注释?

我的第一个想法是,将一个CommentRepository注入我的Post实体,这有什么不好?由于实体和存储库是may域的一部分,为什么它们不能彼此具有双向知识?

谢谢

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

3 个答案:

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

有问题:

  1. 您的模型现在变得不清楚。它包含“techincal”信息,例如_commentIds
  2. 只要您想定义ICommentsRepository,就声称Comment是聚合根。如果我们将agregate模式引入到域模型中,那么应该仅为了agregate根而创建存储库。因此,这意味着CommentPost是不同的agregate根。可能它不是你想要的。
  3. 有更好的解决方案:

    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 agregate的一部分。
    3. 此方法唯一可能的缺点是在使用域对象进行隐式数据库查询时。 Post类的用户必须清楚这一点。

      智能ORM

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