RPM*_*984 5 domain-driven-design ddd-repositories aggregateroot domain-model
我们正在开发一个新项目(重写现有应用程序),我遇到了我的域模型/存储库设计问题.
以下是我们的域模型中两个关键部分的(简化)版本:

正如你所看到的,我有一个帖子的抽象概念,可以是评论,讨论,照片,视频等等.帖子也可以有评论.
我也有一个抽象的位置概念,显然是街道,城市,社区等.
现在,这自然地把我视为两个明确的聚合根.
所以我创建了两个存储库,一个名为PostRepository,另一个名为LocationRepository.
这一切都运行正常,我可以添加/获取任何类型的帖子(或评论),并通过这两个存储库之一添加/获取任何类型的位置.
但现在我正处于城市"登陆页面"的场景中(例如).
在这个页面上,我需要基本上显示"此位置的所有帖子".
这是如何定义的?好吧,帖子可以(可选)在一个位置标记.实现细节,所以我不想深入研究数据(因为这不是DDD的内容),但基本上有地理空间智能来确定哪些帖子包含在位置的形状文件的特定位置,以及标记的Post的纬度/经度.
但是,如何在不跨越边界的情况下检索此信息?
我使用哪个存储库?我需要一个新的吗?
如果它很重要(或者好奇),这是一个Web应用程序(ASP.NET MVC),带有SQL Server 2008数据库和Entity Framework 4.0.
如果您需要任何澄清,请告诉我.
编辑
我们目前使用规范模式的修改版本来检索域模型.
例如,这是我们的BLL中的代码,用于检索Score> = 4的所有Review:
var reviews = postRepository // GenericRepository<Post>
.Find() // IQueryable<Post>
.OfType<Review>() // IQueryable<Review>
.Where(x => x.Score >= 4)
.ToList(); // List<Review>
Run Code Online (Sandbox Code Playgroud)
但现在我需要一些像这样的代码:
var reviews = postRepository
.Find()
.OfType<Review>()
.Where( //lat long, or Locations FK )
.ToList();
Run Code Online (Sandbox Code Playgroud)
问题是我不知道如何在不添加中间连接实体(LocationPost - 因为它是多对多)的情况下执行上述查询,并将FK添加到Post域模型中.
但通过这样做,我越过了总界限 - 不是吗?
为什么这是个问题?根据埃文斯在他的书中,一个AR可能很好地引用另一个AR.(但是,您可能不会从另一个AR引用AR中的子元素)
这些地方真的聚集了根吗?聚合根的定义是它充当一致性的边界.这符合位置的定义吗?我会说一个位置是一个值对象.
这里有两个关于存储库和AR协会的阵营:
一个说所有聚合根必须通过它们各自的存储库获取,并且AR应该使用软关系,例如它们之间的ID
并且说一个聚合根可以很好地获取其他相关的聚合根,并且存储库只是一种查找聚合根的方法.
我会在创建时将帖子绑定到该位置,以便对于每个位置,我可以(通过存储库)获得相关帖子的列表.它看起来像这样:
创建:
var p = new Post(latitude, longitude);
var locations = locationRepository.FindByCoordinates(latitude, longitude);
foreach (var l in locations)
{
l.AssociatePost(p);
}
session.Save(p);
Run Code Online (Sandbox Code Playgroud)
恢复:
var associatedPosts = postRepository.FindByLocation(locationId);
foreach (var p in associatedPosts)
{
Display(p);
}
Run Code Online (Sandbox Code Playgroud)
在幕后,帖子和位置之间的关联将实现为多对多表关系.此解决方案存在一个问题:添加新位置需要扫描所有帖子并将其分配到新位置(如果适用).
希望有所帮助.