2010-09-23 64 views
4

我们的数据团队中有人添加了一个数据库约束,虽然它非常有效且可取,但它为NHibernate带来了很大的问题,因为似乎没有办法覆盖NHibernate的保存顺序。NHibernate - 必须更改保存顺序以满足数据库约束?

给定一个(例如傻)类是这样的:

public Person 
{ 
    public virtual string FirstName { get; set; } 
    public virtual bool IsCurrent { get; set; } 
} 

并且仅在所述背衬表中的一个记录可在同一时间是IsCurrent=true的约束。 。 。

如果我试图通过设置IsCurrent=false来“废弃”现有记录,并用0123'的新记录替换它,我在保存中得到了一个ADO异常,因为NHibernate试图首先执行Insert,违反了SQL Server约束一次只有一条记录可以是IsCurrent=true

我看到两个选项:

  1. 可以在SQL Server配置只在事务结束时检查约束?下面的语句(在旧行的“更新” IsCurrent=false将未打破约束。
  2. 灿NHibernate的保存顺序(同一类型的实例)是 修改或以任何方式“暗示”?

感谢 杰夫

+0

你可以发布你用来保存数据的代码吗?此外,它听起来像你正在为你的实体ID使用SQL Server IDENTITY,它有问题,NHibernate必须实际插入第二条记录,以便在事务完成之前获得它的ID。 – 2010-09-23 02:58:31

回答

1

无论哪种方法是可行的,我会向#2瘦如果您拨打:。

session.saveOrUpdate(person1); 
session.flush(); 
session.saveOrUpdate(person2); 

冲洗将推动SQL语句到数据库我掩饰这将解决您的问题。 (以上是Java Hibernate代码,你的语法可能略有不同)。

+1

选项1是不可能的:MSSQL没有延迟约束。但是,鉴于这一点,我强烈怀疑这个逻辑是真正用触发器强制执行的,而不是一个约束。尽管如此,这并没有真正改变基本问题,最好的解决方案当然是以正确的顺序修改数据。 – Pondlife 2010-09-23 08:26:02

+0

删除额外的逗号 – Pondlife 2010-09-23 08:26:22

+0

+1:直接调用flush可能是处理这个问题的最好方法 – DanP 2010-09-23 11:57:16

-2

这里的问题是,NHibernate没有意识到数据库层中的所有数据整体检查。 如果您在处理数据的时候破解SQL服务器并禁用(短)时间段的约束条件,那么您的选项1是可能的。但这是一个肮脏的解决方案,因为当时正在处理的所有事务都禁用约束。

在这种特殊情况下,我会使用anonter方法: 没有完整性检查。数据整合基于插入或更新时触发触发器。触发器负责将IsCurrent设置为除了当前插入或更新的记录的所有相关记录都为false。当然,你必须处理递归触发器触发,因为触发器是在触发器被触发的同一个表中修改记录的。