我有一个类似于这个设计的设计(尽管有点太小了):
这是一种多对多的关系。扫描可以拥有许多找到的页面,但是找到的页面可能属于许多扫描。
我遇到的问题是我不知道如何在URL上添加唯一约束,因此当保存扫描页面并且已经存在具有此类URL的条目时,它不应该创建新的。相反,新的scan_locatedpage条目应链接到已存在的位置,并且(如果不同)更新其校验和。
只是,我不知道该怎么做。
目前我的代码看起来是这样的:
public LocatedPageMap()
{
Id(x => x.Id);
Map(x => x.Url)
.Not.Nullable();
Map(x => x.Checksum);
HasManyToMany(x => x.ScansFoundWith)
.Cascade.All()
.Inverse()
.Table("Scan_LocatedPage");
}
public ScanMap()
{
Id(x => x.Id);
Map(x => x.Date)
.Not.Nullable();
HasManyToMany(x => x.Located_Pages)
.Cascade.SaveUpdate()
.Table("Scan_LocatedPage");
}
当然,这不起作用。每次保存新扫描时,都会添加新的ArePage,不管是否为Url。
我不知道如何达到这个效果,我不确定在哪里/怎么看。我在标题中读到了许多带有“独特”的多对多问题,但没有找到任何有用的东西。当然'因为我不确定该找到什么。
修改
或许我应该简单地将条件处理程序添加到我的应用程序逻辑中,而不是期望Fluent为我处理这个问题?
答案 0 :(得分:3)
这种问题属于上层层而不是映射。您可以/应该做的是使用提供的URL搜索现有对象LocatedPage
。如果找到 - 使用它,如果没有 - 创建新的。 我们在传入数据绑定期间在上层(服务,业务)上做这些事情。
我想让你注意几点:
1)Chapter 24. Best Practices说:
真正的多对多关联的良好用例很少见。大多数 您需要存储在“链接表”中的其他信息的时间。 在这种情况下,使用两个一对多关联要好得多 中间链接类。事实上,我们认为大多数协会 是一对多和多对一,你在使用任何时都要小心 其他协会风格,并问自己是否真的有必要。
请考虑一下。我们根本没有使用多对多。将中间对象作为完整实体可以带来很多好处(例如,基于子查询进行搜索)
2)级联
在多对多上使用Cascade时要小心。这不是中/配对表的设置。它是为第二端实体设置的。因此,删除LocatedPageMap
后,所有ScansFoundWith
项目(Scan
)也将被删除。通常......级联不是你想要多对多设置的。配对表是“始终级联”