Действительно странно, что поведение выглядит так, как будто оно выполняется БОЛЬШЕ раз, чем оно было на самом деле.Я ожидал бы обратного.Но это не проблема, давайте добавим некоторый контроль параллелизма в ваше приложение.
У вас есть несколько вариантов управления параллелизмом между потоками, которые одновременно обращаются к вашим объектам: оптимистично и пессимистично.
Оптимистичное управление позволит вашим сеансам работать до того времени, когда они попытаются сохранить объект, а затем выдаст исключение.Поймать и обойти исключение может быть очень скучно для вашего пользователя, так как вам, вероятно, придется попросить его повторить ту же операцию, но если число случаев, когда возникают проблемы с совпадением, не имеет значения для вашего контекста, я 'выберите один из них: их влияние на общую производительность вашего приложения меньше.
С другой стороны у вас пессимистический контроль.В этом случае у вас не будет сюрпризов при сохранении объектов, но второй сеанс должен будет ждать, пока первый не завершит свою транзакцию, пока он не сможет продолжить свою работу.Если первый сеанс занимает слишком много времени, очевидно, вы получите какое-то исключение тайм-аута.Если это займет регулярное время, все будет работать, но ваша система будет иметь эту среднюю скорость, пораженную временем блокировки.
Оптимистично - Вариант 1: вы можете сделать какую-то грязную проверку, поэтому NHibernateпроверит, имеет ли объект, который обновляется, те же значения, которые он имел до изменения свойства.Любая разница приведет к исключению.Чтобы настроить его (через Fluent NH), вам нужно добавить что-то похожее на:
OptimisticLock.Dirty().DynamicUpdate();
Включение DynamicUpdate говорит NHibernate проверять только сохраняемые свойства, а не весь объект.Вы можете использовать OptimisticLock.All (), чтобы заставить NHibernate проверять все свойства, но я думаю, что это не нужно в вашем случае.
Оптимистичный - вариант 2: другой вариант - явно указать столбец версии, который будетобрабатываются NH, чтобы узнать, является ли объект, который вы пытаетесь сохранить, наиболее обновленным.Если нет, как обычно, вы получите исключение.Чтобы настроить его с помощью FluentNH:
OptimisticLock.Version();
Version(x => x.Version); // supposing that you have a Version property
Пессимистично: пессимистическая блокировка достигается через перечисление LockMode в ваших методах Get.Как уже говорилось ранее, объект не будет прочитан никаким другим сеансом, пока сеанс владельца не завершит свою транзакцию.Используйте что-то вроде этого:
MappedEntity ent1 = session1.Get<MappedEntity>(entity.Id, LockMode.Force);
Использование любого из этих подходов, вероятно, решит ваши проблемы, но рассмотрите плюсы и минусы каждого в вашем сценарии.
Вся показанная информацияздесь также доступно в блоге Ayende, с соответствующими отображениями HBM.Смотрите это: http://ayende.com/Blog/archive/2009/04/15/nhibernate-mapping-concurrency.aspx
Надеюсь, что это поможет, и дайте мне знать, если я могу помочь вам чем-нибудь еще.
С уважением,
Filipe