【问题标题】:Querying across multiple aggregates with EF when following DDD遵循 DDD 时使用 EF 跨多个聚合进行查询
【发布时间】:2018-06-21 12:46:24
【问题描述】:

在开发我们的新应用程序时,我们正在努力遵循 DDD 的原则。 EF2.1 用于持久化实体。

我们有许多场景,其中具有一个聚合的实体可能会引用另一个聚合中的某些内容。例如,一个订单我有一个客户的参考。在 Order 实体上,我们通过保存外键值来实现这一点。一个过度简化的模型。

public class Order
{
    DateTime OrderDate {get; set;}
    int CustomerId {get; set;}
}

public class Customer
{
    int Id {get
    string Name {get; set;}
}

我们不会将 Order 对象上的任何导航属性包含到 Customer 对象中,因为它会模糊聚合的边界

对于我们可能需要列出订单并包含下订单的客户姓名的要求,团队偏好使用 EF 和 Linq 查询数据并使用 Automapper 映射到 Dto 以返回给客户应用程序。由于没有导航属性,因此很难包含相关的客户来检索名称。

虽然 EF 非常适合持久化聚合,但如果您没有导航属性,使用它来查询读取模型的数据可能会很复杂。在我看来,带有 Dapper 之类的普通旧 SQL 对于这种类型的读取会更容易(并且可能更高效)。团队正在打架,不想使用 SQL。这导致在某些情况下添加导航属性或对实体进行非常复杂的 linq 查询。

是否有人对创建读取模型应采用的方法有任何强烈的看法?

【问题讨论】:

  • 你为什么不连接导航?导航设置潜在的外键以防止孤立记录,使用“包含(x => x.object)”来避免重复调用数据库,以及使用更大的对象。您可以选择使用“包含”或不使用以缩小范围。但是做一个像 'ctx.orders.toList()' 然后 'ctx.People.toList()' 或类似的事情,然后在 C# 中做所有事情,你会通过重复调用来访问数据库并摆脱最好的好处之一英法恕我直言。
  • 我倾向于使用重复的类并将它们映射到各种上下文。在这种情况下,可能会有一个小的 OrderCustomer 类,其中包含适量的属性来服务于 Order 聚合的目的。
  • @djangojazz 围绕 DDD 和聚合设计的许多示例不鼓励持有对其他聚合的引用,并且应该只作为外键。我承认必须有一定程度的实用主义,在这种情况下,这纯粹是为了便于构建读取查询。
  • @stuartmanton 老实说,我对 DDD 的了解一定还不够多。我一直认为这个概念是为单一目的服务的孤立的工作块。我一直认为没有杂乱的模型,但你仍然可以导航。如果您有可以公开设置的外键并且正在进行手动创建,我看不到这样做的好处,所以我很想阅读一篇关于为什么会尝试这样做的论文。在史蒂夫·格林(Steve Greene)给朱莉·勒曼(Julie Lerman)的示例中,似乎并没有摆脱导航,而是更多地关注值类型。

标签: entity-framework domain-driven-design navigation-properties


【解决方案1】:

一个订单我有一个客户的参考。在 Order 实体上,我们通过保存外键值来实现这一点。

列出订单并包含下订单的客户姓名

那么你需要使用Order.CustomerId获取Customer

using(var ctx = new Context())
{
    var orderWithCustomerName = ctx
        .Order
        .Select(o => new OrderWithCustomerName
        {
            Order = o,
            Customer = ctx.Customer.First(c => c.Id == o.CustomerId)
        })
        .ToList();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-13
    • 1970-01-01
    • 2014-06-28
    • 1970-01-01
    相关资源
    最近更新 更多