2017-02-28 88 views
0

有没有办法告诉nHibernate在更新一个具有重复值的行时唯一受到限制的行列上的重复值。NHibernate的唯一约束删除重复

例如(OtherId和动物是复合地唯一约束)

Id | OtherId | Animal 
------------ 
1 | 1  | Dog 
2 | 1  | Cat 
3 | 1  | Bear 
4 | 2  | Dog 

更新ID 3至狗,应导致此

Id | OtherId | Animal 
1 | 1  | NULL 
2 | 1  | Cat 
3 | 1  | Dog 
4 | 2  | Dog 

编辑:

我能够通过在我的表格中创建唯一索引来解决我的问题

CREATE UNIQUE INDEX [Id_OtherId_Animal_Index] 
ON [dbo].[Animals] (OtherId, Animal) 
WHERE Animal IS NOT NULL; 

这样,我防止插入重复(1,狗),仍然允许(2,狗)。这也将允许插入多个(1,NULL)。

接下来,基于Frédéric的建议,我编辑了我的服务层,检查BEFORE插入是否重复。如果它会,那么NULL的动物列将被唯一约束。

回答

1

这个答案已经在OP问题

已经陈旧过时的大幅changes我敢肯定没有这样的功能在NHibernate的或任何其他的ORM。

顺便说一下,在更新到Dog之后应该如何让Cat更新Id 3?

Id | Animal 
1 | 
2 | 
3 | Cat 

如果这意味着ID为1 & 2现在有一个空字符串值,这将是一个违反唯一约束了。
如果它们具有null值,则它依赖于数据库引擎是否符合ANSI null(不认为null等于null)。这不是SQL Server的情况,我知道任何版本,至少在唯一索引的情况下。 (我还没有测试过这个唯一的约束情况。)

无论如何,这种逻辑,更新一行导致其他行的额外更新,必须明确处理。

你有很多选择:

  1. 各分配到Animal属性之前,查询数据库查找,如果另一个具有该名称,并采取对另外一个适当的行动。在处理另一个之后请立即冲洗,以确保在第一个实际更新之前进行处理。
  2. 或者在NHibernate中注入一个event or an interceptor来捕获任何实体上的任何更新,并在那里添加你的重复检查。堆栈溢出有NHibernate事件或拦截器的例子,像这样one
    但是你的情况可能会有点艰难,因为在已经刷新会话的同时刷新其他更改可能会导致麻烦。举例来说,您可能需要直接修改IInterceptor.OnPrepareStatement的sql语句,以便先注入其他更新。
  3. 或者在数据库中处理一些触发器。
  4. 或者由于唯一约束而检测到冲洗失败,请对其进行分析并采取适当的措施。

第三个选项是非常有可能更容易比别人更稳健。

+0

感谢你为这个,我其实就是想什么,如果出了什么更新两列,将空字符串或null,则不会触发这违反唯一约束太多,但我与你的#1和方法去处理这在服务层中,现在听起来更像商业逻辑。 – kotsumu