具有唯一约束和条件更新的多对多

时间:2013-11-28 10:26:39

标签: c# nhibernate fluent-nhibernate fluent-nhibernate-mapping

我有一个类似于这个设计的设计(尽管有点太小了):

MySQL layout design

这是一种多对多的关系。扫描可以拥有许多找到的页面,但是找到的页面可能属于许多扫描。

我遇到的问题是我不知道如何在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为我处理这个问题?

1 个答案:

答案 0 :(得分:3)

这种问题属于上层而不是映射。您可以/应该做的是使用提供的URL搜索现有对象LocatedPage。如果找到 - 使用它,如果没有 - 创建新的。 我们在传入数据绑定期间在上层(服务,业务)上做这些事情。

我想让你注意几点:

1)Chapter 24. Best Practices说:

  

真正的多对多关联的良好用例很少见。大多数   您需要存储在“链接表”中的其他信息的时间。   在这种情况下,使用两个一对多关联要好得多   中间链接类。事实上,我们认为大多数协会   是一对多和多对一,你在使用任何时都要小心   其他协会风格,并问自己是否真的有必要。

请考虑一下。我们根本没有使用多对多。将中间对象作为完整实体可以带来很多好处(例如,基于子查询进行搜索)

2)级联

多对多上使用Cascade时要小心。这不是中/配对表的设置。它是为第二端实体设置的。因此,删除LocatedPageMap后,所有ScansFoundWith项目(Scan)也将被删除。通常......级联不是你想要多对多设置的。配对表是“始终级联”