1

我正在尝试使用 NHibernate 在与从 MVC 应用程序内部在总线上发送消息相同的事务中保存到数据库:

public void DoSomethingToEntity(Guid id)
{
    var session = _sessionFactory.OpenSession();
    CurrentSessionContext.Bind(session);

    using (var transactionScope = new TransactionScope())
    {
        var myEntity = _session.Get(id);
        myEntity.DoSomething();
        _session.Save(myEntity);
        _bus.Send(myMessage);
        transactionScope.Complete();
    }

    session.Dispose();
}

在配置中,.MsmqTransport() 设置为 .IsTransactional(true)。

如果我在消息处理程序中执行此操作(它包含在自己的事务中,因此不需要 TransactionScope),那么一切都按预期工作,如果我包含异常,则两者都失败。

但是,如果我在 MVC 应用程序中自己的事务中执行此操作,则在离开 using 块时,我会在 transactionScope.Complete() 之后收到以下错误:

“该操作对于当前的征募状态无效。”

堆栈跟踪:在 System.Transactions.EnlistmentState.InternalIndoubt(InternalEnlistment enlistment) 在 System.Transactions.VolatileDemultiplexer.BroadcastInDoubt(VolatileEnlistmentSet& volatiles) 在 System.Transactions.TransactionStatePromotedIndoubt.EnterState(InternalTransaction tx) 在 System.Transactions.TransactionStatePromotedBase.InDoubtFromEnlistment(InternalTransaction tx ) 在 System.Transactions.DurableEnlistmentDelegated.InDoubt(InternalEnlistment enlistment, Exception e) 在 System.Transactions.SinglePhaseEnlistment.InDoubt(Exception e) 在 System.Data.SqlClient.SqlDelegatedTransaction.SinglePhaseCommit(SinglePhaseEnlistment enlistment) 在 System.Transactions.TransactionStateDelegatedCommitting.EnterState (InternalTransaction tx) 在 System.Transactions.TransactionStateDelegated。BeginCommit(InternalTransaction tx, Boolean asyncCommit, AsyncCallback asyncCallback, Object asyncState) 在 System.Transactions.CommittableTransaction.Commit() 在 System.Transactions.TransactionScope.InternalDispose() 在 System.Transactions.TransactionScope.Dispose() 在 HumanResources.Application.Implementations C:\Users\paul.davies\Documents\GitHub\EdaCalendarExample\HumanResources.Application\Implementations\HolidayService.cs 中的 .HolidayService.Book(BookHolidayRequest 请求):HumanResources.UI.Controllers.HolidayController.BookUpdate(BookHolidayViewModel viewModel)的第 76 行在 C:\Users\paul.davies\Documents\GitHub\EdaCalendarExample\HumanResources.UI\Controllers\HolidayController.cs:第 82 行,位于 System.Web.Mvc.ActionMethodDispatcher.Execute( ControllerBase 控制器,System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary 的 Object[] 参数)2 parameters) at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary2 个参数)在 System.Web.Mvc.ControllerActionInvoker.<> c_DisplayClass15.b _12() 在 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter 过滤器,ActionExecutingContext preContext,Func`1 延续)

最新编辑:

此代码有效:

public void DoSomethingToEntity(Guid id)
{
    var session = _sessionFactory.OpenSession();
    CurrentSessionContext.Bind(session);

    using (var transactionScope = new TransactionScope())
    {
        var myEntity = _session.Get(id);
        _bus.Send(myMessage);
        transactionScope.Complete();
    }

    session.Dispose();
}

此代码会产生错误:

public void DoSomethingToEntity(Guid id)
{
    var session = _sessionFactory.OpenSession();
    CurrentSessionContext.Bind(session);

    using (var transactionScope = new TransactionScope())
    {
        var myEntity = _session.Get(id);
        myEntity.AnyField = "a new value";
        _bus.Send(myMessage);
        transactionScope.Complete();
    }

    session.Dispose();
}

请注意,在这两个示例中,我都没有保存实体。不同之处在于第二个示例,我正在修改从 NHibernate 获得的实体。这是 100% 可重现的。

4

2 回答 2

4

这可能不相关,但即使会话刷新模式设置为,您仍然必须_session.Flush()在提交之前调用- 这仅适用于 NH 提供的事务。TransactionScopeCommit

于 2012-09-21T14:17:04.460 回答
0

据我所知,在创建新 System.Transactions.Transaction 时无法收到通知,并且查看 NHibernate 中的代码,它似乎没有任何代码来处理创建 TransactionScope 的情况创建会话之后。

创建会话时,它会尝试加入当前事务,如果没有,则会话不会加入事务。我怀疑这是导致事务在提交时失败的原因。

我建议在 TransactionScope 内创建会话 - 还要检查您是否在 TransactionScope 之前的某处调用 session.BeginTransaction。

于 2012-09-19T16:22:59.417 回答