C# 如何与NHibernate和Envers交换唯一、有序的列条目?

C# 如何与NHibernate和Envers交换唯一、有序的列条目?,c#,.net,nhibernate,swap,nhibernate-envers,C#,.net,Nhibernate,Swap,Nhibernate Envers,我和NHibernate一起工作了一段时间,终于遇到了一个问题,我既找不到答案,也找不到其他人怎么会有这个问题。 历史保存环境为NHibernate 3.3.1.4000和NHibernate.Envers 1.4 我有以下类型的数据库表/实体类: public class ProcedureStep { public virtual int Id { get; protected internal set; } public virtual Procedure ParentOb

我和NHibernate一起工作了一段时间,终于遇到了一个问题,我既找不到答案,也找不到其他人怎么会有这个问题。 历史保存环境为NHibernate 3.3.1.4000和NHibernate.Envers 1.4

我有以下类型的数据库表/实体类:

public class ProcedureStep
{
    public virtual int Id { get; protected internal set; }
    public virtual Procedure ParentObject { get; set; }
    public virtual int StepNo { get; set; }
    public virtual string Name { get; set; }
}
使用映射:

public class ProcedureStepMap : ClassMap<ProcedureStep>
{
    public ProcedureStepMap()
    {
        Table("ProcedureStep");
        Id(x => x.Id);

        References(x => x.ParentObject).Not.Nullable().UniqueKey("UK_PO_SN");
        Map(x => x.StepNo).Not.Nullable().UniqueKey("UK_PO_SN");
        Map(x => x.Name).Not.Nullable();
    }
}
但现在NHibernates开始发挥作用了。在提交事务时,NHibernate不知道关于步骤1的任何信息,因此尝试只使用2个数据库更新命令(步骤2和步骤3),由于StepNo列的唯一性,这两个命令不起作用。 在步骤1之后添加session.flush()并不会改变这种行为(我很理解,因为我们在一个事务中)

下一个想法是使用
session.CreateQuery(“update…”).ExecuteUpdate()
对数据库进行更改,这很好,但正在围绕Envers进行操作,我没有关于此更改的历史记录(同样可以理解,因为sql刚刚传递)

但是,在一个事务中处理所有事务并拥有Envers的历史记录的情况下,进行这种更改的正确方法是什么? 难道不让“StepNo”列唯一化是让它工作的唯一方法吗? 不希望失去专栏的独特性,因为重要的是要有一个propper排序,让数据库确保这一点,这将是一个很大的帮助

首先感谢你的想法

[解决方案]:

jbl和cremor似乎是唯一的答案。
连同其他一些问题,我们现在决定完全跳过Envers,使用更专业的方式进行历史管理,不太通用,更适合我们的需要。如果没有enver,使用sql命令进行简单的三步更新就可以解决问题。

如果您的数据库支持可延迟约束,我将使用它们。

集合是如何映射的?作为一套,包还是清单?如果您使用的是列表-您需要在子对象上使用“stepno”吗?您是对的@jokofaile,似乎不使用特定的SQL语句是不可能的@Roger:它映射为列表,抱歉,忘记发布该部分了。但是我看不出有什么区别,因为StepNo有一个数据库列,它在对象模型中不需要它。但是异常来自数据库,而不是对象模型。但我会更仔细地研究它。@jbl:。。。但是使用CreateQuery的特定SQL将在Envers周围工作,因此这也不起作用,这是问题的一部分。如果您使用的是sqlserver,恐怕它不支持延迟约束。在两个事务中可以做到这一点:第一个事务随集合的大小增加所有项索引。第二次交易将项目放回正确的位置。但是,这似乎是非常人为的,性能贪婪,会在您的版本系统中产生噪音…非常感谢,这似乎真的是让一切工作正常并维护数据库检查的方法。有没有可能让NHibernate生成契约作为可延期约束?@JokoFacile我不这么认为。但是,使用
应该是可能的:对于快速测试,这似乎是可行的,但只有在Oracle中,SQLite目前用于开发目的,不支持可延迟的唯一键,只支持可延迟的外键约束。但这至少是最终生产系统的解决方案。我会把这个问题再留一点时间,也许会有其他的想法。。。
(1) Aaaa
(2) Bbbb <--
(3) Cccc
(4) Dddd
(1) Bbbb <--
(2) Aaaa
(3) Cccc
(4) Dddd
Begin Transaction
1) Set "Aaaa" to StepNo = 0
2) Set "Bbbb" to StepNo = 1
3) Set "Aaaa" to StepNo = 2
End Transaction