如果重复

时间:2017-02-28 21:11:05

标签: sql .net nhibernate

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

例如(OtherId和Animal是复合唯一约束的)

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

将Id 3更新为Dog,应该导致此

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的建议,我编辑了我的服务层,以便在插入之前检查它是否重复。如果是,那么NULL动物列将被唯一约束。

1 个答案:

答案 0 :(得分:1)

OP问题中的实质性changes已经过时了这个答案

我很确定NHibernate或任何其他ORM中没有这样的功能。

顺便说一下,在将它更新为Dog之后,应该将哪些产品更新为Cat?

Id | Animal
1  | 
2  | 
3  | Cat

如果这意味着Id 1& 2现在具有空字符串值,那么这也将是一个唯一的约束违规。
如果它们具有null值,那么它依赖于db引擎是否符合ANSI null(null不被视为等于null)。这不是SQL Server的情况,我知道的任何版本,至少对于唯一索引的情况。 (我没有测试过唯一约束案例。)

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

你有很多选择:

  1. 在每次分配Animal属性之前,查询数据库以查找另一个是否具有该名称,并对另一个名称采取适当的操作。在处理完另一个之后立即进行冲洗,以确保在实际更新第一个之前对其进行处理。
  2. 或者在NHibernate中注入event or an interceptor以捕获任何实体的任何更新,并在那里添加检查重复项。 Stack Overflow有NHibernate事件或拦截器的例子,比如one 但是你的情况可能会有点困难,因为在已经刷新会话的同时刷新其他一些更改可能会引起麻烦。您可能必须使用IInterceptor.OnPrepareStatement作为示例直接修改sql语句,以便首先将其他更新注入其中。
  3. 或者使用DB中的某个触发器来处理它。
  4. 或者检测由于唯一约束导致的刷新失败,对其进行分析并采取适当的措施。
  5. 第三种选择很可能比其他选项更容易和更强大。