Asp.net nhibernate死锁
我正在ASP.NET页面中使用以下代码创建一条记录,然后对记录进行计数,以确保没有超过设置的限制,如果超过了,则回滚事务Asp.net nhibernate死锁,asp.net,sql-server,nhibernate,Asp.net,Sql Server,Nhibernate,我正在ASP.NET页面中使用以下代码创建一条记录,然后对记录进行计数,以确保没有超过设置的限制,如果超过了,则回滚事务 using (var session = NhibernateHelper.OpenSession()) using (var transaction = session.BeginTransaction()) { session.Lock(mall, LockMode.None); var voucher = new Voucher(); vouc
using (var session = NhibernateHelper.OpenSession())
using (var transaction = session.BeginTransaction())
{
session.Lock(mall, LockMode.None);
var voucher = new Voucher();
voucher.FirstName = firstName ?? string.Empty;
voucher.LastName = lastName ?? string.Empty;
voucher.Address = address ?? string.Empty;
voucher.Address2 = address2 ?? string.Empty;
voucher.City = city ?? string.Empty;
voucher.State = state ?? string.Empty;
voucher.Zip = zip ?? string.Empty;
voucher.Email = email ?? string.Empty;
voucher.Mall = mall;
session.Save(voucher);
var issued = session.CreateCriteria<Voucher>()
.Add(Restrictions.Eq("Mall", mall))
.SetProjection(Projections.Count("ID"))
.UniqueResult<int>();
if (issued >= mall.TotalVouchers)
{
transaction.Rollback();
throw new VoucherLimitException();
}
transaction.Commit();
return voucher;
}
使用(var session=NhibernateHelper.OpenSession())
使用(var transaction=session.BeginTransaction())
{
session.Lock(mall,LockMode.None);
var凭证=新凭证();
凭证.FirstName=FirstName??字符串.空;
凭证.LastName=LastName??字符串.空;
凭证.地址=地址??字符串.空;
凭证.Address2=Address2??字符串.空;
凭证.城市=城市??字符串.空;
凭证.State=状态??字符串.Empty;
凭证.Zip=Zip??字符串.空;
凭证.Email=Email??字符串,空;
购物中心=购物中心;
会话保存(凭证);
var issued=session.CreateCriteria()
.Add(限制条件Eq(“商场”,商场))
.SetProjection(Projections.Count(“ID”))
.UniqueResult();
如果(已发行>=购物中心总凭单)
{
transaction.Rollback();
抛出新VoucherLimitException();
}
Commit();
退货凭证;
}
然而,我遇到了一大堆僵局。我假设发生这种情况是因为我正在尝试统计我刚刚执行插入的表中的记录,而插入的行上仍然持有锁,从而导致死锁
- 有人能证实这一点吗
- 有人能提出解决办法吗
这种设计很容易死锁——通常(并非总是)一个连接本身不可能死锁,但针对同一个表执行插入和聚合的多个连接很可能死锁。这是因为,虽然从执行工作的连接的角度来看,一个事务中的所有活动看起来都是完整的——db不会从“自己的”记录中锁定一个事务——但来自其他事务的聚合查询会试图同时锁定整个表或其中的大部分,而这些查询会死锁 在本例中,Read Uncommitted不是您的朋友,因为它基本上说是“忽略锁”,这意味着违反了您在数据方面设置的规则。即,表中记录的计数将不准确,您将根据不准确的计数进行操作。当实际答案为11时,计数将返回10或13 我最好的建议是重新安排插入逻辑,这样就可以捕获计数的概念,而不必逐行计数。你可以往几个方向走。我的一个想法是:用序列对插入的凭证进行编号,并对序列本身进行限制
对于读取未提交的数据错误,请检查以下内容:(免责声明:Merrill Aldrich是我:-)理论上,凭证永远不会被删除甚至更新。此外,出于性能原因,我倾向于避免使用触发器(尽管纯度也是一个不错的选择),但假设凭证经常被删除。什么样的正确方法可以确保通过插入凭证,我从未超过任意限制?如果凭证没有被删除,我只需在尝试插入.JBland之前检查(mall.dictions.Count