【问题标题】:Query data across multiple repositories in DDD在 DDD 中跨多个存储库查询数据
【发布时间】:2017-07-07 13:55:40
【问题描述】:

我在 DDD 有界上下文中使用多个聚合根。

例如

public class OrderAggregate
{
    public int ID {get;set;}
    public string Order_Name {get;set;}
    public int Created_By_UserID {get;set;}
}

public class UserAggregate
{
    public int ID {get;set;}
    public string Username {get;set;}
    public string First_Name {get;set;}
    public string Last_Name {get;set;}
}

我正在使用 SQL 关系库来持久化域对象。每个聚合根匹配一个存储库。

如果我想查找由 John Doe 创建的订单(搜索多个聚合),那么 DDD 的方式是什么?

  • 将 First_Name 和 Last_Name 添加到 OrderAggregate 以在 OrderRespository 中添加 FindByUserFirstLastName 方法,但这可能会引发两个聚合根之间的数据一致性问题

  • 创建原始 sql 查询并直接访问数据库,以便跨“存储库”进行搜索

  • 使用“finders”直接从 DB 中加入实体

  • 将完成查询所需的数据复制到新的聚合根,例如


public class QueryOrderAggregate
{
    public int ID { get; set; }
    public string Order_Name { get; set; }
    public int Created_By_UserID { get; set; }
    public string First_Name { get; set; }
    public string Last_Name { get; set; }
}

【问题讨论】:

  • 不要让数据库模型支配你的域模型
  • 您有两个有界上下文:Ordering 和 UserManagement
  • @ConstantinGALBENU 不,这只是错误的解释
  • 如果您确定(并且只有您可以)只有一个有界上下文(只有一个普遍存在的语言边界),那么您不应该根据查询要求对聚合(写入模型)进行建模(读取模型)。因此,在这种情况下,不使用 CQRS,您应该使用选项 2 或 3。
  • 如果您确实使用 CQRS,那么您只需要构建一个包含查询所需的所有信息的新读取模型,而无需使用任何 joins

标签: domain-driven-design ddd-repositories


【解决方案1】:

如果我想查找由 John Doe 创建的订单(搜索多个聚合),那么 DDD 的方式是什么?

与访问聚合的方式几乎相同...

您创建一个存储库,该存储库提供一个(无论此视图/报告在您的域中的名称是什么)。它可能使用 UserId 作为识别报告的键。在存储库的实现中,实现可以做任何有意义的事情——SQL 连接是一个合理的起点。

View/Report 基本上是一个值类型;它是不可变的,可以提供数据,但没有任何方法,也没有对聚合根的任何直接访问。例如,视图可能包含 OrderId,但要真正获取订单聚合根,您必须调用 那个 存储库上的方法。

跨越多个聚合的视图是完全可以接受的,因为您实际上无法使用该视图修改任何内容。对底层状态的更改仍然通过聚合根,这提供了一致性保证。

视图是数据的过时快照的表示形式。消费者不应期望它会神奇地更新——如果您想要更新的内容,请返回存储库获取新副本。

【讨论】:

    猜你喜欢
    • 2018-04-04
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-01
    • 1970-01-01
    相关资源
    最近更新 更多