Как поменять уникальные упорядоченные записи столбцов с помощью 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 вступают в игру. NHibernate ничего не знает о шаге 1 при фиксации транзакции и поэтому пытается работать только с 2 командами обновления базы данных (шаги 2 и 3), которые не работают, из-за уникального символа столбца StepNo. Добавление session.flush() после шага 1 ничего не меняет в этом поведении (мне это вполне понятно, так как мы находимся в транзакции).

Следующая идея была просто с помощью session.CreateQuery("update...").ExecuteUpdate() внести изменения в базу данных, которая работает нормально, но работает вокруг Envers и оставляет меня без записи истории для этого изменения (вполне понятно, еще раз, так как sql только что передан).

Но как правильно сделать это изменение, имея все в одной транзакции и историю Envers? Может быть, не сделать столбец "StepNo" уникальным - единственный способ заставить его работать? Потеря уникального символа столбца не была бы желательна, так как важно иметь упорядоченный порядок и наличие базы данных, обеспечивающей это, было бы большой помощью.

Спасибо заранее за ваши идеи!

[Решение]:

JBL и Кремор, кажется, имеют единственные ответы. Вместе с некоторыми другими проблемами мы решили полностью пропустить Envers и использовать более специализированный способ управления историей, менее общий, более адаптированный к нашим потребностям. Без Envers проблему можно решить с помощью простого трехэтапного обновления с использованием команд sql.

1 ответ

Решение

Если ваша база данных поддерживает отложенные ограничения, я бы их использовал.

Другие вопросы по тегам