【问题标题】:NHibernate unique constraint remove if duplicateNHibernate 唯一约束如果重复则删除
【发布时间】:2017-02-28 21:11:05
【问题描述】:

有没有办法告诉 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, Dog) 并仍然允许 (2, Dog)。这也将允许插入多个 (1, NULL)。

接下来,根据下面 Frédéric 的建议,我编辑了我的服务层以在插入之前检查它是否会重复。如果是,则 NULL 将对其进行唯一约束的动物列。

【问题讨论】:

    标签: sql .net nhibernate


    【解决方案1】:

    OP 问题中的大量changes 已经过时了这个答案

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

    顺便说一句,在将 Id 3 更新为 Dog 后,应该将它更新为 Cat 的结果是什么?

    Id | Animal
    1  | 
    2  | 
    3  | Cat
    

    如果这意味着 Id 1&2 现在具有空字符串值,那也将违反唯一约束。
    如果它们具有 null 值,则取决于数据库引擎是否符合 ANSI null 标准(null 不被视为等于 null)。这不是 SQL Server 的情况,我知道的任何版本,至少对于唯一索引的情况。 (我还没有测试过唯一约束情况。)

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

    你有很多选择:

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

    第三个选项很可能比其他选项更容易且更健壮。

    【讨论】:

    • 谢谢你,我实际上只是想如果将两列都更新为空字符串或 null 那么不会触发唯一约束违规,但我会同意你的#1 方法然后在服务层处理这个问题,现在听起来更像是业务逻辑。
    猜你喜欢
    • 2017-02-23
    • 2012-05-11
    • 2012-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-13
    • 2012-07-26
    • 2012-10-07
    相关资源
    最近更新 更多