Nhibernate устанавливает период ожидания запроса для команд и пессимистическую блокировку

#c# #sql-server-2005 #nhibernate

#c# #sql-server-2005 #nhibernate

Вопрос:

Я хочу указать определенный тайм-аут команды (или LOCK_TIMEOUT) для SQL, и как только это время истекает, в NHibernate должно быть вызвано исключение (или предупреждение).
Ниже приведен пример псевдокода, который я написал:

 using (var session = sessionFactory.OpenSession()) {
    using (var sqlTrans = session.BeginTransaction()) {
        ICriteria criteria = session.CreateCriteria(typeof(Foo));
        criteria.SetTimeout(5); //Here is the specified command timout, eg: property SqlCommand.CommandTimeout
        Foo fooObject = session.Load<Foo>(primaryKeyIntegerValue, LockMode.Force);
        session.SaveOrUpdate(fooObject);
        sqlTrans.Commit();
    }
}  
  

В SQL server мы использовали для достижения этого следующий SQL:

 BEGIN TRAN
SET LOCK_TIMEOUT 500   
SELECT * FROM Foo WITH (UPDLOCK, ROWLOCK) WHERE PrimaryKeyID = 1000001
  

Если строка PrimaryKeyID была бы заблокирована в другой транзакции, SQL Server выдает следующее сообщение об ошибке:

 Msg 1222, Level 16, State 51, Line 3
Lock request time out period exceeded
  

Аналогично я хочу показать время ожидания блокировки или информацию о времени ожидания команды, используя NHibernate. Пожалуйста, помогите мне добиться этого.
Заранее спасибо за вашу помощь.

Комментарии:

1. В вашем коде C # указан 5-секундный тайм-аут, в то время как в SQL он равен 0,5 секунды.

Ответ №1:

Для достижения пессимистической блокировки вам необходимо получить сведения об объекте с помощью ICritiera.
Измененный код приведен ниже:

 using (var session = sessionFactory.OpenSession()) {
    using (var sqlTrans = session.BeginTransaction()) {
        ICriteria criteria = session.CreateCriteria<Foo>();
        criteria.Add(Restrictions.Eq(fieldOnWhichYouWishToGetTheLock, fieldValue));
        criteria.SetLockMode(LockMode.Upgrade);
        criteria.SetTimeout(5);
        Foo fooObject = (Foo)criteria.List<Foo>();
        //Make the changes to foo object and save as usual.
    }
}
  

Комментарии:

1. Привет @ NRao, решение работает для меня. Пожалуйста, дайте мне знать, как также получить блокировку для нескольких полей.

2. Не был бы LockMode. Принудительно в исходном коде уже выполняется пессимистическая блокировка?

Ответ №2:

Интересно, могли бы вы адаптировать этот подход к своим целям? Конечно, это не было бы автоматическим. и это означало бы, что переданное в resourceName, вероятно, должно быть конкатенацией вашего типа объекта и его PK.

В качестве альтернативы, command_timeout выглядит многообещающе, но я не вижу способа сделать это (для обновлений) каким-либо иным способом, кроме общесистемного.