“交易已中止”即使在故意中止时也会被抓住
Posted
技术标签:
【中文标题】“交易已中止”即使在故意中止时也会被抓住【英文标题】:"The transaction has aborted" getting caught even when intentionally aborting 【发布时间】:2021-07-19 14:43:09 【问题描述】:关于我如何使用TransactionScope
的一些上下文,截至目前在程序中,如果三个数据库的查询中的任何一个出现错误,我这样做是为了让TransactionScope
将dispose
一切导致没有数据通过。这部分程序运行良好。
另一个背景是我使用的框架是 ASP.NET Boilerplate。
出于保密原因,以下代码将减去一些细节。
public CUDResult TriTransaction(TransactItem[] item)
CUDResult result = new CUDResult();
using (TransactionScope ts = new TransactionScope())
try
result = InsertItem(item);
if (result.success == false)
return result;
ts.Complete();
catch (Exception)
ts.Dispose();
return result;
return result;
现在担心的是,我正在使用的框架会将dispose
视为服务器错误,并且始终会针对所述服务器错误An internal error occurred during your request
返回已修复的错误消息。
虽然后端按我想要的方式工作,但我希望 dispose
不会被捕获为服务器错误并导致前端显示上述错误消息。
下面将记录错误消息。
ERROR 2021-04-26 14:34:04,260 [::1] [Chrome90] [20] Abp.WebApi.ExceptionHandling.AbpApiExceptionFilterAttribute - The transaction has aborted.
System.Transactions.TransactionAbortedException: The transaction has aborted.
at System.Transactions.TransactionStateAborted.BeginCommit(InternalTransaction tx, Boolean asyncCommit, AsyncCallback asyncCallback, Object asyncState)
at System.Transactions.CommittableTransaction.Commit()
at System.Transactions.TransactionScope.InternalDispose()
at System.Transactions.TransactionScope.Dispose()
at Abp.EntityFramework.Uow.TransactionScopeEfTransactionStrategy.Commit()
at Abp.EntityFramework.Uow.EfUnitOfWork.CompleteUow()
at Abp.Domain.Uow.UnitOfWorkBase.Complete()
at Abp.Domain.Uow.UnitOfWorkInterceptor.PerformSyncUow(IInvocation invocation, UnitOfWorkOptions options)
at Abp.Domain.Uow.UnitOfWorkInterceptor.PerformUow(IInvocation invocation, UnitOfWorkOptions options)
at Abp.Domain.Uow.UnitOfWorkInterceptor.Intercept(IInvocation invocation)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Abp.Auditing.AuditingInterceptor.PerformSyncAuditing(IInvocation invocation, AuditInfo auditInfo)
at Abp.Auditing.AuditingInterceptor.Intercept(IInvocation invocation)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Abp.Runtime.Validation.Interception.ValidationInterceptor.Intercept(IInvocation invocation)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.XXXAppServiceProxy.TriTransaction(TransactItem[] item)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Abp.WebApi.Controllers.Dynamic.Interceptors.AbpDynamicApiControllerInterceptor`1.Intercept(IInvocation invocation)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.DynamicApiController`1Proxy_4.TriTransaction(TransactItem[] item)
at lambda_method(Closure , Object , Object[] )
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass6_2.<GetExecutor>b__2(Object instance, Object[] methodParameters)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Tracing.ITraceWriterExtensions.<TraceBeginEndAsyncCore>d__17`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Tracing.ITraceWriterExtensions.<TraceBeginEndAsyncCore>d__17`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Abp.WebApi.Uow.AbpApiUowFilter.<ExecuteActionFilterAsync>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Tracing.ITraceWriterExtensions.<TraceBeginEndAsyncCore>d__17`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Abp.WebApi.Validation.AbpApiValidationFilter.<ExecuteActionFilterAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Tracing.ITraceWriterExtensions.<TraceBeginEndAsyncCore>d__17`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Abp.WebApi.Auditing.AbpApiAuditFilter.<ExecuteActionFilterAsync>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Tracing.ITraceWriterExtensions.<TraceBeginEndAsyncCore>d__17`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Abp.WebApi.Security.AntiForgery.AbpAntiForgeryApiFilter.<ExecuteAuthorizationFilterAsync>d__10.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Tracing.ITraceWriterExtensions.<TraceBeginEndAsyncCore>d__17`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Abp.WebApi.Authorization.AbpApiAuthorizeFilter.<ExecuteAuthorizationFilterAsync>d__7.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Tracing.ITraceWriterExtensions.<TraceBeginEndAsyncCore>d__17`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Controllers.AuthenticationFilterResult.<ExecuteAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__6.MoveNext()
我怀疑这可能不仅仅是 dispose
被作为错误捕获的事实,而且可能完全是另外一回事,但我对此没有足够的知识,想知道是否有任何方法可以解决每当有意处置事务时前端总是显示An internal error occurred during your request
错误消息的问题。
【问题讨论】:
只有在InsertItem(item)
抛出错误时才会出现这种情况吗?
在 InsertItem(item) 中捕获错误的任何时候,result.success 将设置为 false 并返回结果,根据我对 TransactionScope 工作原理的理解有效调用 ts.dispose .所以在某种程度上,是的,它只发生在 InsertItem(item) 抛出错误时。
我需要重新表述我的问题:只有当 InsertItem(item)
内抛出的异常冒泡到 using 块内的 catch (Exception)
时才会发生这种情况?
那么你的问题可能是你调用了两次 dispose 。 using
语句实际上只是 TransactionScope ts = new TransactionScope; try ... finally ts.Dispose()
的语法糖。查看this 看看它是如何在代码中实现的
您正在处理两次,因为您有一个 using
块。只需删除行 ts.Dispose();
它不需要
【参考方案1】:
您的问题是您两次调用Dispose
,您永远不需要手动调用Dispose
,这就是using
语句的用途。 using (...)
基本上只是一些 syntactic sugar 用于 try/finally 块。所以这个:
using (var foo = new Foo())
foo.SayHello();
编译为
Foo foo = new Foo();
try
foo.SayHello();
finally
if (foo != null)
((IDisposable)foo).Dispose();
意味着你的代码被编译为
CUDResult result = new CUDResult();
TransactionScope ts = new TransactionScope();
try
try
result = InsertItem(item);
if (!result.success) // instead of result.success == false
return result;
ts.Complete();
catch (Exception)
ts.Dispose();
return result;
finally
if (ts != null)
((IDisposable)ts).Dispose();
return result;
这很明显,当捕获到异常时,您将处理 ts
两次
【讨论】:
我已经删除了dispose
,但错误仍然出现在前端。我感谢您的解释,但我不认为导致前端错误的问题是因为 ts
被处理了两次。以上是关于“交易已中止”即使在故意中止时也会被抓住的主要内容,如果未能解决你的问题,请参考以下文章
即使 IAM 角色具有完整的 Redshift 权限,AWS Lambda 在调用 Redshift 的“CreateCluster”操作时也会出现“拒绝访问”错误
为什么dev_appserver.py即使在空闲时也会使用这么多CPU?