我在使用 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 开始发挥作用了。 NHibernate 在提交事务时对第 1 步一无所知,因此尝试仅对数据库使用 2 个更新命令(第 2 步和第 3 步),由于 StepNo 列的唯一性,该命令不起作用。 在第 1 步之后添加 session.flush() 不会改变该行为的任何内容(我很容易理解,因为我们在一个事务中)。
下一个想法是使用 session.CreateQuery("update...").ExecuteUpdate()
对数据库进行更改,这工作正常,但正在解决 Envers 和让我没有此更改的历史记录(再次完全可以理解,因为 sql 刚刚传递)。
但是,将所有内容都放在一次交易中并拥有 Envers 的历史记录,进行这种改变的正确方法是什么? 难道不使“StepNo”列唯一是让它工作的唯一方法吗? 不希望失去列的唯一性,因为正确排序很重要,并且让数据库确保这一点,这将有很大帮助。
预先感谢您的想法!
[解决方案]:
jbl 和 cremor 似乎是唯一的答案。 连同其他一些麻烦点,我们现在决定完全跳过 Envers 并使用更专业的方式来进行历史管理,不那么笼统,更适合我们的需要。在没有 Envers 的情况下,可以使用 sql 命令通过简单的 3 步更新来解决问题。
最佳答案
如果您的数据库支持可延迟约束,我会使用它们。
关于c# - 如何使用 NHibernate 和 Envers 交换唯一的、排序的列条目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14752916/