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