简体   繁体   English

NHibernate等效于SQL“ UPDATE table SET column = column +…”

[英]NHibernate Equivalent to SQL “UPDATE table SET column = column + …”

I'm trying to update Quantity of a Product in a sale system using NHibernate. 我正在尝试使用NHibernate更新销售系统中的Product Quantity

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

However, NHibernate will generate an SQL in this form: 但是,NHibernate将以这种形式生成SQL:

        UPDATE Product SET quantity = 2 WHERE id = 1;

If another client updates product quantity while this code is processing, the quantity will be incorrect . 如果在此代码处理过程中另一个客户更新了产品数量,则数量将不正确 The solution I can think of so far is to lock that row before making the update: 到目前为止,我能想到的解决方案是在进行更新之前锁定该行:

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

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

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

However, this can affect other client if I need to update a long list of products. 但是,如果我需要更新一长串产品,这可能会影响其他客户端。

Is there an equivalent method in NHibernate to generate SQL like: NHibernate中是否有等效的方法来生成SQL,例如:

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

?

any suggestion? 有什么建议吗?

Update 更新资料

I've tried opening session with serializable isolation level as @Fran suggested: 我已经尝试过以@Fran建议使用可序列化隔离级别打开会话:

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

The problem is when the row is modified by another client before this transaction is committed, an exception occurs: 问题是,在提交该事务之前,另一客户修改了该行时,会发生异常:

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

does that mean we need to explicitly lock every row that need updating? 这是否意味着我们需要显式锁定需要更新的每一行? ie: 即:

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

if the locking is necessary, what is the different between opening transaction with and without IsolationLevel.Serializable ? 如果需要锁定,则在有和没有IsolationLevel.Serializable的情况下打开事务有什么区别?

the only way I see doing this is locking the object in a serializable transaction. 我看到的唯一方法是将对象锁定在可序列化的事务中。

so when you open your transactions give it an Isolation level of serializable. 因此,当您打开交易记录时,请为它提供一个可序列化的隔离级别。 This will lock the object until you commit the transaction. 这将锁定对象,直到您提交事务。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM