首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我在这里正确地使用了nHIbernate的ITransaction吗?

我在这里正确地使用了nHIbernate的ITransaction吗?
EN

Stack Overflow用户
提问于 2012-06-13 20:54:18
回答 1查看 214关注 0票数 0

我只是在学习nHibernate,遇到了一个可能很简单的问题需要解决。

因此,我已经了解到,到目前为止,您不能/不应该在彼此之间嵌套nHibernate事务;在我的示例中,当范围转到另一个例程并启动一个新事务时,我发现了这一点。

那么我应该做以下几件事?

代码语言:javascript
复制
using (ITransaction transaction = session.BeginTransaction())
{
    NHibernateMembership mQuery =
        session.QueryOver<NHibernateMembership>()
            .Where(x => x.Username == username)
            .And(x => x.ApplicationName == ApplicationName)
            .SingleOrDefault();

    if (mQuery != null)
    {
        mQuery.PasswordQuestion = newPwdQuestion;
        mQuery.PasswordAnswer = EncodePassword(newPwdAnswer);
        session.Update(mQuery);

        transaction.Commit();
        passwordQuestionUpdated = true;
    }
}

// Assume this is in another routine elsewhere but being
// called right after the first in the same request
using (ITransaction transaction = session.BeginTransaction())
{
    NHibernateMembership mQuery =
        session.QueryOver<NHibernateMembership>()
            .Where(x => x.Username == username)
            .And(x => x.ApplicationName == ApplicationName)
            .SingleOrDefault();

    if (mQuery != null)
    {
        mQuery.PasswordQuestion = newPwdQuestion;
        mQuery.PasswordAnswer = EncodePassword(newPwdAnswer);
        session.Update(mQuery);

        transaction.Commit();
        passwordQuestionUpdated = true;
    }
}

注:我知道它们只是一个副本,我只是在演示我的问题

第一个问题是这样做的吗?每次交易?

第二个问题,我需要调用transaction.Commit();每次调用还是只在最后一组调用?

第三个问题,,有更好的方法,自动化的还是手动的?

第三个问题是否可以使用session.Transaction.IsActive来确定“当前会话”是否已经是事务的一部分--因此在这种情况下,我可以在最高级别进行“事务包装”,比方说work代码,并在其中调用例程,然后在结束时提交所有工作。这是有缺陷的方法吗?

我真的很想把它写下来,所以我开始我的意思是继续;我不想找到1000行代码,因为我需要全部改变它。

提前谢谢。

编辑:

所以我写了一些代码来解释我的问题。

代码语言:javascript
复制
private void CallingRoutine()
{
    using(ISession session = Helper.GetCurrentSession)
    {
        using (ITransaction transaction = session.BeginTransaction())
        {
            //  RUN nHIbernate QUERY to get an OBJECT-1

            //  DO WORK on OBJECT

            //  Need to CALL an EXTERNAL ROUTINE to finish work
            ExternalRoutine();

            //  DO WORK on OBJECT-1 again

            //  *** At this point ADO exception triggers
        }
    }
}

private bool ExternalRoutine()
{
    using(ISession session = Helper.GetCurrentSession)
    {
        using (ITransaction transaction = session.BeginTransaction())
        {
            //  RUN nHIbernate QUERY to get an OBJECT-2

            //  DO WORK on OBJECT

            //  Determine result
            if(Data)
            {
                return true;
            }

            return false;
        }
    }
}

希望这证明了这个问题。这是我理解写事务的方式,但是注意到ADO异常是如何发生的。很明显我做错了什么。我怎么能写这些例行公事呢?

例如,如果我要为某个提供程序编写一个助手对象,并且在每个公开的例程中都有一个nHibernate查询运行--假设我对调用函数和数据一无所知,那么我编写这些例程的时间有多长--我的工作是有效和高效地使用nHibernate并返回一个结果。

这就是我在ExternalRoutine()中如何编写事务的假设--假设这是nHibernate的唯一使用,并显式地进行事务处理。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-06-14 09:34:52

如果可能,我建议使用System.Transactions.TransactionScope:

代码语言:javascript
复制
using(var trans = new TransactionScope()) 
using(var session = .. create your session...) {
    ... do your stuff ...
    trans.Complete();
}

trans.Complete将导致会话刷新和提交事务,此外,您还可以拥有嵌套的事务处理范围。这唯一的“缺点”是,如果您有多个连接(或登记了资源,如MSMQ),它将升级到DTC,但这并不一定是一个缺点,除非您使用的是MySQL之类的东西,它与DTC没有很好的关系。

对于简单的情况,如果没有错误,我可能会在BeginRequest中使用事务范围,并在EndRequest中提交它(如果您使用的是ASP.NET MVC,则使用过滤器),但这在很大程度上取决于您在做什么--只要您的操作是短的(它们应该在web应用程序中),这应该是可以的。创建会话和事务范围的开销并不大,它应该会导致访问静态资源(或不需要会话的资源)的问题,除非您查看的是一个非常高容量/高性能的网站。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11023141

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档