NHibernate相当于SQL“更新表集列=列+…”

NHibernate相当于SQL“更新表集列=列+…”,nhibernate,concurrency,Nhibernate,Concurrency,我正在尝试使用NHibernate更新销售系统中的产品数量 using (var session = NHibernateSessionUtil.OpenSession()) { using (var trans = session.BeginTransaction()) { var product = session.Load<Product>(1);

我正在尝试使用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();
            }
        }
如果另一个客户端在处理此代码时更新产品数量,则数量将不正确。 到目前为止,我能想到的解决方案是在进行更新之前锁定该行:

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

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

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

有什么建议吗

更新

我已尝试使用@Fran建议的可序列化隔离级别打开会话:

    ...
    using (var trans = session.BeginTransaction(IsolationLevel.Serializable))
    ...
问题是,在提交此事务之前,另一个客户端修改行时,会发生异常:

    {"ERROR: 40001: could not serialize access due to concurrent update"}
这是否意味着我们需要显式锁定需要更新的每一行?i、 e:


如果需要锁定,那么使用IsolationLevel.Serializable和不使用IsolationLevel.Serializable打开事务有什么不同?

我认为这样做的唯一方法是在可序列化事务中锁定对象


因此,当您打开事务时,给它一个可序列化的隔离级别。这将锁定对象,直到您提交事务。

我看到的唯一方法是在可序列化事务中锁定对象


因此,当您打开事务时,给它一个可序列化的隔离级别。这将锁定对象,直到您提交事务。

这可能会起作用:session.CreateQueryUPDATE产品集数量=数量+2,其中id=:id.SetParameterid,1.ExecuteUpdate@菲罗:这个代码有效,谢谢。但是,是否有任何配置可以让NHibernate/Fluent NHibernate生成SQL,而不是我们手动编写?这是HQL不是SQL,但您也可以检查Fran的答案。@Firo:谢谢澄清。这可能有效:session.CreateQueryUPDATE产品集数量=数量+2,其中id=:id.SetParameterid,1.ExecuteUpdate@菲罗:这个代码有效,谢谢。但是,是否有任何配置使NHibernate/Fluent NHibernate生成SQL而不是我们手动编写?这是HQL不是SQL,但您也可以检查Fran的答案。@Firo:谢谢您的澄清。谢谢您指出这一点。我不熟悉IsolationLevel.Serializable。我这样做对吗?请参考我的最新资料来指出这一点。我不熟悉IsolationLevel.Serializable。我这样做对吗?请参考我的更新
    ...
    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);