gpt4 book ai didi

NHibernate、事务和 TransactionScope

转载 作者:行者123 更新时间:2023-12-04 01:23:34 29 4
gpt4 key购买 nike

我正在尝试找到在使用 NHibernate 的 Web 应用程序中处理事务的最佳解决方案。
我们使用 IHttpModule 并在 HttpApplication.BeginRequest 我们打开一个新 session 并使用 ManagedWebSessionContext.Bind(context, session); 将其绑定(bind)到 HttpContext;我们关闭并取消绑定(bind) HttpApplication.EndRequest 上的 session 。
根据 best practice,在我们的 Repository 基类中,我们总是围绕 SaveOrUpdate、Delete、Get 方法包装事务。 :

        public virtual void Save(T entity)
{
var session = DependencyManager.Resolve<ISession>();
using (var transaction = session.BeginTransaction())
{
session.SaveOrUpdate(entity);
transaction.Commit();
}
}
但这不起作用,如果您需要在某处放置事务,例如一个应用程序服务,包括对保存、删除等的多个存储库调用。
所以我们尝试的是使用 TransactionScope(我不想编写自己的事务管理器)。为了测试这是否有效,我使用了一个不调用 .Complete() 的外部 TransactionScope 来强制回滚:
存储库保存():
    public virtual void Save(T entity)
{
using (TransactionScope scope = new TransactionScope())
{
var session = DependencyManager.Resolve<ISession>();
session.SaveOrUpdate(entity);
scope.Complete();
}
}
使用存储库的 block :
        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"));
这行不通。但对我来说,如果 NHibernate 支持 TransactionScope 它会!发生的情况是数据库中根本没有 ROLLBACK 但是当 testRepository.GetById(testEntity.Id);语句执行了一个带有 SET Text = "TestCahgned"的 UPDATE 代替触发(它应该在 BEGIN TRAN 和 ROLLBACK TRAN 之间触发)。 NHibernate 从 level1 缓存中读取值并触发 UPDATE 到数据库。不是预期的行为!?据我了解,每当在 NHibernate 范围内完成回滚时,您还需要关闭并取消绑定(bind)当前 session 。
我的问题是:有谁知道使用 TransactionScope 和 ManagedWebSessionContext 的好方法?

最佳答案

我采取了非常相似的方法。在 HttpModule 中,我向 sessionfactory 请求一个新 session + 当新请求进来时绑定(bind)它。但我也在这里开始事务。然后,当请求结束时,我只需解除绑定(bind)并尝试提交事务。

此外,我的基础存储库不会以任何方式进行 session - 它会询问当前 session ,然后对 session 执行一些工作。此外,我不会在这个基类中用事务包装任何东西。相反,整个 http 请求是一个工作单元。

这可能不适合您正在处理的项目,但我更喜欢这种方法,因为每个请求都会作为单个原子单元失败或成功。我有一篇完整的博文 here如果您对实际实现感兴趣,请使用源代码。

以下是此基础存储库的示例:

public abstract class NHibernateRepository<T> where T : class
{

protected readonly ISessionBuilder mSessionBuilder;

public NHibernateRepository()
{
mSessionBuilder = SessionBuilderFactory.CurrentBuilder;
}

public T Retrieve(int id)
{
ISession session = GetSession();

return session.Get<T>(id);
}

public void Save(T entity)
{
ISession session = GetSession();

session.SaveOrUpdate(entity);
}

public void Delete(T entity)
{
ISession session = GetSession();

session.Delete(entity);
}

public IQueryable<T> RetrieveAll()
{
ISession session = GetSession();

var query = from Item in session.Linq<T>() select Item;

return query;
}

protected virtual ISession GetSession()
{
return mSessionBuilder.CurrentSession;
}
}

关于NHibernate、事务和 TransactionScope,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1518855/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com