关于System.Data.Entity.Infrastructure.CommitFailedException的两项技术问询
错误堆栈信息
System.Data.Entity.Infrastructure.CommitFailedException: An error was reported while committing a database transaction but it could not be determined whether the transaction succeeded or failed on the database server. See the inner exception and http://go.microsoft.com/fwlink/?LinkId=313468 for more information. ---> System.NullReferenceException: Object reference not set to an instance of an object. at System.Data.SqlClient.SqlInternalTransaction.GetServerTransactionLevel() at System.Data.SqlClient.SqlInternalTransaction.CheckTransactionLevelAndZombie() at System.Data.SqlClient.SqlInternalTransaction.Commit() at System.Data.SqlClient.SqlTransaction.Commit() at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext](TTarget target, Action`2 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed) --- End of inner exception stack trace --- at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext](TTarget target, Action`2 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed) at System.Data.Entity.Infrastructure.Interception.DbTransactionDispatcher.Commit(DbTransaction transaction, DbInterceptionContext interceptionContext) at System.Data.Entity.Core.EntityClient.EntityTransaction.Commit() at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess) at System.Data.Entity.Core.Objects.ObjectContext.<>c__DisplayClass59.<ExecuteStoreCommand>b__57() at System.Data.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation) at TestLite.Infrastructure.Data.Repository.BaseRepository`1.Isolate(Int32 statelevel) at TestLite.Infrastructure.Data.Repository.BaseRepository`1.Read(Int64 id) at TestLite.Business.AppService.Controllers.PropertyController.GetDataPayment(String reftype, Int64 reference, Int32 customertype, Int32 ordertype, Int32 isPartsOrder)
问题1:如何模拟该System.Data.Entity.Infrastructure.CommitFailedException错误?
- 反射篡改内部对象:通过反射获取
SqlInternalTransaction实例的私有字段(如_internalConnection),将其设置为null,之后调用事务的Commit方法,会触发GetServerTransactionLevel()中的空引用异常,最终被EF包装为CommitFailedException。 - EF拦截器注入异常:实现
DbTransactionInterceptor,在Commit操作的执行阶段抛出NullReferenceException,EF会自动将该异常封装为目标异常。 - 构造异常连接场景:在事务提交前,手动关闭底层数据库连接(通过反射获取
SqlConnection并调用Close),此时提交事务会因内部连接对象为空触发空引用,进而引发CommitFailedException。
问题2:为何空引用问题会引发数据库事务提交失败?
从堆栈轨迹可知,空引用发生在SqlInternalTransaction.GetServerTransactionLevel()方法中,这是SqlClient提交事务的关键校验步骤:
- 提交事务时,SqlClient需要先获取数据库端的事务层级,确认事务处于有效状态,才能执行后续提交逻辑。
- 若该方法中访问的内部对象(如数据库连接实例、事务状态对象)为空,会直接抛出
NullReferenceException,中断提交流程。 - EF捕获到底层异常后,无法确认数据库服务器是否已经执行了提交操作(异常发生在提交结果确认环节),因此会将底层异常包装为
CommitFailedException,提示事务结果未知。
内容的提问来源于stack exchange,提问作者Divakar Upadhyay
相关产品推荐
相关产品推荐

