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