我想为每个异步控制器操作应用TransactionScope。我不想在每个动作中都这样做,而是在中心位置进行,以便它适用于所有动作。我尝试创建一个继承自ApiControllerActionInvoker的自定义IHttpActionInvoker
public class ControllerActionTransactionInvoker : ApiControllerActionInvoker
{
public override Task<HttpResponseMessage> InvokeActionAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken)
{
using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
Task<HttpResponseMessage> result;
result = base.InvokeActionAsync(actionContext, cancellationToken);
scope.Complete();
return result;
}
}
}
然后在Web Api的Startup类中用新创建的一个替换默认的IHttpActionInvoker
config.Services.Replace(typeof(IHttpActionInvoker), new ControllerActionTransactionInvoker());
现在,我可以调用控制器操作并获得结果,但是我手动为一系列Db操作引发了异常,并且所需的事务处理过程不起作用。所以在DB中完成了部分工作。 在Azure api应用程序中托管api之后它根本不起作用。它说没有找到控制器动作。
如何解决这个问题?
答案 0 :(得分:1)
您的scope
正在完成并在控制器操作执行完毕之前被处理,因为您没有等待响应。请尝试这样:
public class ControllerActionTransactionInvoker : ApiControllerActionInvoker
{
public override async Task<HttpResponseMessage> InvokeActionAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken)
{
using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
HttpResponseMessage result = await base.InvokeActionAsync(actionContext, cancellationToken);
scope.Complete();
return result;
}
}
}
虽然这可能很有效,但您可能还想考虑在Web API堆栈中更高层次 - 可能在处理程序中 - 因为您可能会错过其他事务活动,例如处理程序,过滤器等取决于您想要进出的范围。