Domain driven design DDD-如何避免在此处跨越聚合边界?

Domain driven design DDD-如何避免在此处跨越聚合边界?,domain-driven-design,ddd-repositories,domain-model,aggregateroot,Domain Driven Design,Ddd Repositories,Domain Model,Aggregateroot,我们正在进行一个新项目(重新编写现有的应用程序),我的域模型/存储库设计遇到了问题 以下是我们域模型中两个关键部分的(简化)版本: 如你所见,我对帖子有一个抽象概念,可以是评论、讨论、照片、视频等。帖子也可以有评论 我还有一个关于位置的抽象概念,它显然是街道、城市、街区等 现在,在我看来,这自然是两个清晰的聚合根 因此,我创建了两个存储库,一个名为PostRepository,另一个名为LocationRepository 这一切都很好,我可以添加/获取任何类型的帖子(或评论),并通过这两个存

我们正在进行一个新项目(重新编写现有的应用程序),我的域模型/存储库设计遇到了问题

以下是我们域模型中两个关键部分的(简化)版本:

如你所见,我对帖子有一个抽象概念,可以是评论、讨论、照片、视频等。帖子也可以有评论

我还有一个关于位置的抽象概念,它显然是街道、城市、街区等

现在,在我看来,这自然是两个清晰的聚合根

因此,我创建了两个存储库,一个名为PostRepository,另一个名为LocationRepository

这一切都很好,我可以添加/获取任何类型的帖子(或评论),并通过这两个存储库之一添加/获取任何类型的位置

但现在我在一个城市的“登录页”场景中(例如)

在这个页面上,我需要基本上显示“这个位置的所有帖子”

这是如何定义的?嗯,可以(可选地)在某个位置标记帖子。实现细节,所以我不想深入研究数据(因为DDD不是关于数据的),但本质上有地理空间智能,可以通过位置的形状文件和标记的帖子的纬度/经度来确定特定位置包含哪些帖子

但是,我如何在不跨越边界的情况下检索这些信息呢

我应该使用哪个存储库?我需要一个新的吗

如果有必要(或者出于好奇),这是一个web应用程序(ASP.NET MVC),带有SQL Server 2008数据库和实体框架4.0

如果您需要任何澄清,请告诉我

编辑

我们目前使用规范模式的修改版本来检索域模型

例如,这是BLL中的代码,用于检索得分>=4的所有评审:

var reviews = postRepository // GenericRepository<Post>
      .Find() // IQueryable<Post>
      .OfType<Review>() // IQueryable<Review>
      .Where(x => x.Score >= 4)
      .ToList(); // List<Review>
var reviews=postRepository//GenericRepository
.Find()//IQueryable
.OfType()//IQueryable
.其中(x=>x.得分>=4)
.ToList();//列表
但现在我需要这样的代码:

var reviews = postRepository
    .Find()
    .OfType<Review>()
    .Where( //lat long, or Locations FK )
    .ToList();
var reviews=postRepository
.Find()
第()类
.Where(//lat long或位置FK)
.ToList();
问题是,我不知道如何在不添加中间连接实体(LocationPost,因为它是多对多)的情况下执行上述查询,并在Post域模型中添加FK


但是通过这样做,我跨越了聚合边界,不是吗?

假设您使用了规范模式,您可以使用位置对象构建Post规范吗?然后,您只需将规范传递给您的帖子存储库,并返回结果。

我会在创建时将帖子绑定到该位置,以便(通过存储库)为每个位置获取关联帖子的列表。它看起来是这样的:

var reviews = postRepository
    .Find()
    .OfType<Review>()
    .Where( //lat long, or Locations FK )
    .ToList();
创建:

var p = new Post(latitude, longitude);
var locations = locationRepository.FindByCoordinates(latitude, longitude);
foreach (var l in locations)
{
    l.AssociatePost(p);
}
session.Save(p);
检索:

var associatedPosts = postRepository.FindByLocation(locationId);
foreach (var p in associatedPosts)
{
    Display(p);
}
在后台,posts和location之间的关联将作为多对多表关系来实现。此解决方案存在一个问题:添加新位置需要扫描所有帖子并将其分配到新位置(如果适用)

希望有帮助。

为什么这是个问题? 根据埃文斯在书中的说法,一个AR很可能引用另一个AR。 (但是,您不能从另一个AR引用AR中的子元素)

此外,位置真的是聚合根吗? 聚合根的定义是,它充当一致性的边界。 这符合位置的定义吗? 我认为位置是一个有价值的对象

关于存储库和AR关联,这里几乎有两个阵营:

一种说法是,所有聚合根都必须通过各自的存储库获取,AR应该使用软关系,例如它们之间的ID


还有一种说法是聚合根可以很好地获取其他相关的聚合根,而存储库仅仅是找到聚合根的一种方法。

Hmm,从未听说过“标准模式”。或者您指的是规范模式?(我们使用了该方法的一个修改版本——通过C#表达式)@RPM1984你能在pastebin/gist上发布“修改的规范模式”方法并将其链接放到这里吗?我闻到了一些有趣的东西。@RPM1984:这就是为什么我在谷歌上找不到它的原因!:)是的,这就是我的意思。@Arnis L.-很高兴见到你,我们再热烈讨论一下DDD好吗?只是开玩笑。:)事实上,我刚刚看了一段关于DDD项目失败的7个原因的NDC视频,这让我大吃一惊。没有太多的代码,我没有在任何地方“找到”它-
public-ICollection-FindAll(表达式谓词):其中t:Post
是域服务上的一个方法(也称为PostServices),可以这样使用:
var-reviews=\u-postService.FindAll(x=>x.ReviewScore>=5)。该实现使用
上的谓词作用于
通用存储库
。我到办公室后会试试这个,我会告诉你我的进展。干杯。:)我使用了此解决方案的修改版本。你的整体解决方案为我指明了正确的方向,干杯。+1-回答得好。对于OP来说,即使有点晚了,如果你认为某个位置是“论坛”,而帖子本身就是,那么你的模型符合经典的“讨论论坛”格式。在处理聚合边界以及一对多和多对多关系时,您会发现这是一种非常常见的模式。但所有地点都有一个标识(LocationId),并且它们都有一个纬度/经度,这也是唯一的。但它们又是不可变的,所以它们可能是值对象。