【发布时间】:2010-08-20 09:55:52
【问题描述】:
我正在尝试将 TransactionScope 与 NHibernate 一起使用,以便在一个事务中调用多个方法。数据存储方法是这样的:
public virtual void Save(T dataObject)
{
try
{
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.RepeatableRead }))
{
this.session.SaveOrUpdate(dataObject);
scope.Complete();
}
}
catch (Exception ex)
{
bool rethrow = ExceptionPolicy.HandleException(ex, "Data Layer Policy");
if (rethrow)
{
throw;
}
}
}
public T GetByNumber(string documentNumber) { T文档=空; 尝试 { 使用 (TransactionScope 范围 = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.RepeatableRead })) { 文档 = this.Session.CreateCriteria(typeof(T)) .Add(Restrictions.Eq("Number", documentNumber)) .UniqueResult(); 范围。完成(); } } 捕捉(例外前) { bool rethrow = ExceptionPolicy.HandleException(ex, "Data Layer Policy"); 如果(重新抛出) { 扔; } } 退货文件; }
我想测试事务中的行/表锁定,所以我做了几个单元测试和一些控制台应用程序。以下是这些控制台应用程序的代码:
更新的应用程序:
const string DocumentNumber = "386774321";
Random randomGenerator = new Random();
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.RepeatableRead }))
{
using (BillingDocumentRepository billingDocumentRepository = new BillingDocumentRepository())
{
BillingOrderData orderData = billingDocumentRepository.GetByNumber(DocumentNumber);
orderData.Notes = randomGenerator.Next().ToString();
Console.WriteLine(string.Format("SECOND: {0}: Updated notes to {1}.", DateTime.Now.ToString("HH:mm:ss.fffff"), orderData.Notes));
Console.WriteLine(string.Format("SECOND: {0}: Updating order.", DateTime.Now.ToString("HH:mm:ss.fffff")));
Console.WriteLine(string.Format("SECOND: {0}: Going to sleep for 10000ms.", DateTime.Now.ToString("HH:mm:ss.fffff")));
Sleep(10000); // My custom sleep method because I didn't want to use Thread.Sleep for simulating long transaction
billingDocumentRepository.Save(orderData);
}
Console.WriteLine(string.Format("SECOND: {0}: Going to sleep for 10000ms.", DateTime.Now.ToString("HH:mm:ss.fffff")));
Sleep(10000);
Console.WriteLine(string.Format("SECOND: {0}: Completing transaction.", DateTime.Now.ToString("HH:mm:ss.fffff")));
scope.Complete();
}
读取数据库中同一行的应用程序:
while (true)
{
using (BillingDocumentRepository repository = new BillingDocumentRepository())
{
Console.WriteLine(string.Format("MAIN: {0}: Getting document.", DateTime.Now.ToString("HH:mm:ss.fffff")));
BillingOrderData billingOrderData = repository.GetByNumber("386774321");
Console.WriteLine(string.Format("MAIN: {0}: Got order with notes {1}.", DateTime.Now.ToString("HH:mm:ss.fffff"), billingOrderData.Notes));
Sleep(1000);
}
}
问题是第一个事务(更新行)在任何时候都不会锁定行以供读取。第二个应用程序一直在使用 scope.Complete() 之前的旧值和之后的新值读取该行。如何使用此模型实现锁定?
【问题讨论】:
标签: nhibernate transactions locking transactionscope