我只是在学习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来确定“当前会话”是否已经是事务的一部分--因此在这种情况下,我可以在最高级别进行“事务包装”,比方说work代码,并在其中调用例程,然后在结束时提交所有工作。这是有缺陷的方法吗?
我真的很想把它写下来,所以我开始我的意思是继续;我不想找到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的唯一使用,并显式地进行事务处理。
发布于 2012-06-14 09:34:52
如果可能,我建议使用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,则使用过滤器),但这在很大程度上取决于您在做什么--只要您的操作是短的(它们应该在web应用程序中),这应该是可以的。创建会话和事务范围的开销并不大,它应该会导致访问静态资源(或不需要会话的资源)的问题,除非您查看的是一个非常高容量/高性能的网站。
https://stackoverflow.com/questions/11023141
复制相似问题