如何使用NHibernate和Envers交换唯一的订购列条目?

时间:2013-02-07 14:00:20

标签: 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 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();
    }
}

我们有一个父对象,其中包含一系列过程步骤。用户现在可以添加,删除或修改不同的步骤。一个“修改”是使用按钮在步骤列表中向上或向下移动选定项目来更改程序步骤的顺序。

让我们举一个具体的例子:

该方案是4个程序步骤1-4的列表:

(1) Aaaa
(2) Bbbb <--
(3) Cccc
(4) Dddd

用户选择第二项“Bbbb”并按“向上”按钮,以获得:

(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

但现在NHibernates正在发挥作用。由于StepNo列的独特特性,NHibernate在提交事务时对步骤1一无所知,因此只尝试使用2个数据库更新命令(步骤2和3),这些命令不起作用。 在步骤1之后添加session.flush()不会改变任何行为(对我来说是完全可以理解的,因为我们在事务中)。

下一个想法就是使用session.CreateQuery("update...").ExecuteUpdate()来对数据库进行更改,这样做工作正常,但是正在使用Envers并让我没有这个更改的历史记录(再次可以理解,因为sql刚刚传递完毕。)

但是,如果在一次交易中拥有所有内容并拥有Envers的历史,那么进行此更改的正确方法是什么? 可能是,没有让“StepNo”列独一无二是让它运行的唯一方法吗? 不希望失去该列的独特特性,因为让一个propper订购并让数据库确保这一点非常重要,这将是一个很大的帮助。

感谢你的想法!

[解决方法]:

jbl和cremor似乎只有答案。 连同其他一些麻烦点,我们现在决定完全跳过Envers并使用更专业的方式进行历史管理,不那么通用,更适合我们的需求。没有Envers,只需使用sql命令进行简单的3步更新即可解决问题。

1 个答案:

答案 0 :(得分:0)

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