我有一个使用NHibernate的ASP.NET应用程序,可以根据用户操作以事务方式更新几个表。涉及一个日期范围,只能在表“预订”中输入一个条目,以便指定独家日期。
我的问题是如何防止竞争条件,即两个用户动作几乎同时发生,并导致多个条目进入> 1日期的“预订”。在调用.Commit()之前我无法检查,因为我认为仍会留下竞争条件?
我所能看到的只是在提交后进行检查并手动滚动更改,但这让我的嘴巴口感非常糟糕! :)
booking_ref(INT)PRIMARY_KEY AUTOINCREMENT
booking_start(DATETIME)
booking_end(DATETIME)
答案 0 :(得分:5)
session.BeginTransaction(IsolationLevel.Serializable
),并在同一事务中检查并插入。一般情况下,您不应该将isolationlevel设置为可序列化,只是在这种情况下。或
在检查并最终插入之前锁定表。您可以通过nhibernate:
触发SQL查询来完成此操作session.CreateSQLQuery(“SELECT null as dummy FROM Booking WITH(tablockx,holdlock)”)。AddScalar(“dummy”,NHibernateUtil.Int32); 这将在该事务的持续时间内仅锁定该表以进行选择/插入。
希望有所帮助
答案 1 :(得分:0)
上述解决方案可作为选项使用。如果我通过使用“Parallel.For”发送了100个请求,而事务级别是可序列化的,则yess没有重复的reqeust id但是25个事务失败。这对我的客户来说是不可接受的。所以我们修复了问题,只存储请求id并在其他表上添加一个唯一索引作为temp。
答案 2 :(得分:-1)
您的数据库应该管理您的数据完整性。
您可以将“日期”列设为唯一。因此,如果2个线程试图获得相同的日期。一个人将抛出一个唯一的密钥违规,另一个将成功。