我只是在学习nHibernate并且遇到了可能需要解决的简单问题。
是的,所以到目前为止我已经想到你不能/不应该把nHibernate交易嵌套在彼此之内;在我的情况下,当范围转到另一个例程并且我开始一个新的事务时,我想出了这个。
我应该做以下事情吗?
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来确定“当前会话”是否已经是事务的一部分 - 所以在这种情况下我可以在最高级别进行“事务处理”,比如说Web表单代码,然后让例程在其中调用,然后在最后完成所有工作。这是一种有缺陷的方法吗?
我真的想要把它打倒,所以我开始,因为我的意思是继续;我不想找到1000行代码,我需要更改它们。
提前致谢。
修改
是的,所以我写了一些代码来解释我的问题。
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的唯一用途并明确地进行事务。
答案 0 :(得分:0)
如果可能,我建议使用System.Transactions.TransactionScope:
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则使用过滤器),但这实际上很大程度上取决于什么你正在做 - 只要你的操作很短(他们应该在网络应用程序中),这应该没问题。创建会话和事务范围的开销并不大,它应该导致访问静态资源(或不需要会话的资源)的问题,除非您正在查看真正高容量/高性能的网站。 / p>