NHibernate Эквивалентно SQL "UPDATE таблица SET столбец = столбец + ..." - PullRequest
2 голосов
/ 11 октября 2011

Я пытаюсь обновить Quantity Product в системе продаж с использованием NHibernate.

        using (var session = NHibernateSessionUtil.OpenSession())
        {
            using (var trans = session.BeginTransaction())
            {
                var product = session.Load<Product>(1);
                product.Quantity += 2;
                session.SaveOrUpdate(product);
                trans.Commit();
            }
        }

Однако NHibernate сгенерирует SQL в этой форме:

        UPDATE Product SET quantity = 2 WHERE id = 1;

Если другой клиент обновляет количество товара во время обработки этого кода, оно будет неверно . Решение, о котором я могу думать до сих пор, заключается в блокировке этой строки перед обновлением:

                ...
                var product = session.Load<Product>(1);

                // lock row for update
                session.Lock(product, LockMode.Upgrade);

                product.Quantity += 2;
                session.SaveOrUpdate(product);
                ...

Однако это может повлиять на другого клиента, если мне потребуется обновить длинный список продуктов.

Существует ли в NHibernate эквивалентный метод для генерации SQL, например:

    UPDATE Product SET quantity = quantity + 2 WHERE id = 1;

?

есть предложения?

Обновление

Я попытался открыть сеанс с сериализуемым уровнем изоляции, как предложил @Fran:

    ...
    using (var trans = session.BeginTransaction(IsolationLevel.Serializable))
    ...

Проблема заключается в том, что при изменении строки другим клиентом до совершения этой транзакции возникает исключение:

    {"ERROR: 40001: could not serialize access due to concurrent update"}

означает ли это, что нам нужно явно заблокировать каждую строку, которая требует обновления? т.е.:

    var product = session.Load<Product>(1, LockMode.Upgrade);

если блокировка необходима, чем отличается транзакция открытия от IsolationLevel.Serializable ?

1 Ответ

0 голосов
/ 12 октября 2011

единственный способ сделать это - заблокировать объект в сериализуемой транзакции.

, поэтому при открытии транзакций задайте для него уровень изоляции сериализуемой.Это будет блокировать объект, пока вы не совершите транзакцию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...