Tôi đang cố gắng tìm giải pháp tốt nhất để xử lý giao dịch trong một ứng dụng web sử dụng NHibernate.NHibernate, giao dịch và TransactionScope
Chúng tôi sử dụng IHttpModule và tại HttpApplication.BeginRequest chúng tôi mở phiên mới và liên kết nó với HttpContext với ManagedWebSessionContext.Bind (ngữ cảnh, phiên); Chúng tôi đóng và hủy liên kết phiên trên HttpApplication.EndRequest.
Trong lớp cơ sở Repository của chúng tôi, chúng tôi luôn quấn một giao dịch xung quanh SaveOrUpdate của chúng tôi, Xóa, nhận các phương pháp như thế nào, theo best practice:
public virtual void Save(T entity)
{
var session = DependencyManager.Resolve<ISession>();
using (var transaction = session.BeginTransaction())
{
session.SaveOrUpdate(entity);
transaction.Commit();
}
}
Nhưng sau đó điều này không làm việc, nếu bạn cần phải đặt một giao dịch ở đâu đó trong ví dụ Dịch vụ ứng dụng để bao gồm một số lệnh lưu trữ vào Lưu, Xóa, v.v.
Vì vậy, những gì chúng tôi đã thử là sử dụng TransactionScope (Tôi không muốn viết trình quản lý giao dịch của riêng mình). Để kiểm tra điều này làm việc, tôi sử dụng một TransactionScope ngoài mà không gọi .Complete() để buộc một rollback:
Kho Lưu():
public virtual void Save(T entity)
{
using (TransactionScope scope = new TransactionScope())
{
var session = DependencyManager.Resolve<ISession>();
session.SaveOrUpdate(entity);
scope.Complete();
}
}
Khối sử dụng kho :
TestEntity testEntity = new TestEntity { Text = "Test1" };
ITestRepository testRepository = DependencyManager.Resolve<ITestRepository>();
testRepository.Save(testEntity);
using (var scope = new TransactionScope())
{
TestEntity entityToChange = testRepository.GetById(testEntity.Id);
entityToChange.Text = "TestChanged";
testRepository.Save(entityToChange);
}
TestEntity entityChanged = testRepository.GetById(testEntity.Id);
Assert.That(entityChanged.Text, Is.EqualTo("Test1"));
Điều này không hiệu quả. Nhưng với tôi nếu NHibernate hỗ trợ TransactionScope nó sẽ! Điều xảy ra là không có ROLLBACK nào trong cơ sở dữ liệu nhưng khi testRepository.GetById (testEntity.Id); tuyên bố được thực hiện một UPDATE với SET Text = "TestCahgned" được kích hoạt thay vào đó (Nó nên đã được bắn giữa BEGIN TRAN và ROLLBACK TRAN). NHibernate đọc giá trị từ bộ nhớ cache level1 và kích hoạt một UPDATE vào cơ sở dữ liệu. Không mong đợi hành vi !? Từ những gì tôi hiểu bất cứ khi nào một rollback được thực hiện trong phạm vi NHibernate bạn cũng cần phải đóng và unbind phiên hiện tại.
Câu hỏi của tôi là: Có ai biết cách tốt để làm điều này bằng cách sử dụng TransactionScope và ManagedWebSessionContext không?
Nếu bạn đang sử dụng TransactionScope, bạn cần sử dụng NHibernate 2.1. Nó chỉ với 2.1 mà NH thực sự tích hợp tốt với TransactionScope. –