发送内部的TransactionScope NServiceBus消息(Sending NServi

2019-10-17 06:16发布

我试图使用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(真)。

如果我做这一个消息处理程序(它被包裹在自己的事务,从而不需要的TransactionScope)里面然后一切按预期工作,如果我有一个例外,都失败。

但是,如果我在MVC应用程序做我自己的事务中,我得到以下错误transactionScope.Complete()离开using块时后:

“操作是无效的入伍的当前状态。”

堆栈跟踪:在System.Transactions.EnlistmentState.InternalIndoubt(InternalEnlistment征募)在System.Transactions.VolatileDemultiplexer.BroadcastInDoubt在System.Transactions.TransactionStatePromotedBase.InDoubtFromEnlistment在System.Transactions.TransactionStatePromotedIndoubt.EnterState(VolatileEnlistmentSet&挥发物)(InternalTransaction TX)(InternalTransaction TX )在System.Transactions.DurableEnlistmentDelegated.InDoubt(InternalEnlistment征募,例外五)在System.Transactions.SinglePhaseEnlistment.InDoubt(例外五)在System.Data.SqlClient.SqlDelegatedTransaction.SinglePhaseCommit(SinglePhaseEnlistment征募)在System.Transactions.TransactionStateDelegatedCommitting.EnterState (InternalTransaction TX)在System.Transactions.TransactionStateDelegated.BeginCommit(InternalTransaction TX,布尔asyncCommit,的AsyncCallback的AsyncCallback,对象asyncState)在System.Transactions.CommittableTransaction.Commit()在System.Transactions.TransactionScope.Inter nalDispose()在System.Transactions.TransactionScope.Dispose()在HumanResources.Application.Implementations.HolidayService.Book(BookHolidayRequest请求)在C:\用户\ paul.davies \文件\ GitHub的\ EdaCalendarExample \ HumanResources.Application \实现\ HolidayService的.cs:线76在HumanResources.UI.Controllers.HolidayController.BookUpdate(BookHolidayViewModel视图模型)在C:\用户\ paul.davies \文件\ GitHub的\ EdaCalendarExample \ HumanResources.UI \控制器\ HolidayController.cs:线82在lambda_method(闭合,ControllerBase,在System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase控制器对象[]),在System.Web.Mvc.ReflectedActionDescriptor.Execute对象[]参数)(ControllerContext controllerContext,IDictionary的2 parameters) at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary 2个参数)在System.Web.Mvc.ControllerActionInvoker。<> C_ DisplayClass15.b _12()在SY stem.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%可再现。

Answer 1:

这可能不相关,但你还是要调用_session.Flush()犯了之前TransactionScope即使会话刷新模式设置为Commit -这仅适用于NH提供的交易。



Answer 2:

至于我可以告诉是没有的创建一个新的System.Transactions.Transaction时被通知,并期待在NHibernate的代码方式,它似乎没有任何代码来处理这种情况是创建TransactionScope的地方AFTER创建会话。

当你创建会话,它会尝试在当前事务中登记,如果没有一个那么会话不会在事务中登记。 我怀疑这是什么导致失败上提交事务。

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



文章来源: Sending NServiceBus message inside TransactionScope