EntityFramework:当发生异常时,Database.CurrentTransaction变为空

时间:2018-05-08 13:10:49

标签: c# entity-framework orm entity-framework-6 entity-framework-4

今天我遇到了Entity Framework的奇怪问题。 请考虑以下课程:

public partial class Entities
{
 ...
 public void DocumentUpdateForSync(string userLogin, IEntrySync document)
 {
    var timeEntry = document as Domain.Documents.TimeEntry;        
    Database.BeginTransaction();                
            try
            {

                mobileTimeEntryUpdate(userLogin,
                                      timeEntry.Id,
                                      timeEntry.ProjectId,
                                      timeEntry.ActivityTypeId,
                                      timeEntry.FileAs,
                                      timeEntry.StartTime,
                                      timeEntry.Duration,
                                      timeEntry.Comments,                                          
                                     readAfterUpdate:false).FirstOrDefault();                    
            }
            catch (Exception e)
            {
                //Here Database.CurrentTransaction becomes null
                //I want to handle errors silently, not rolling back transaction
            }
             ...
             Database.CurrentTransaction?.Commit();
 }

}

此类是自动生成的类的一部分,由EF创建。它继承自DbContext类。 mobileTimeEntryUpdate方法是存储过程的自动生成包装器:

public virtual ObjectResult<mobileTimeEntryGet_Result> mobileTimeEntryUpdate(string userLogin, Nullable<int> iD, Nullable<int> projectID, Nullable<int> activityTypeID, string fileAs, Nullable<System.DateTime> startTime, Nullable<int> duration, string comments, Nullable<bool> readAfterUpdate)
    {
        var userLoginParameter = userLogin != null ?
            new ObjectParameter("UserLogin", userLogin) :
            new ObjectParameter("UserLogin", typeof(string));

        var iDParameter = iD.HasValue ?
            new ObjectParameter("ID", iD) :
            new ObjectParameter("ID", typeof(int));

        var projectIDParameter = projectID.HasValue ?
            new ObjectParameter("ProjectID", projectID) :
            new ObjectParameter("ProjectID", typeof(int));

        var activityTypeIDParameter = activityTypeID.HasValue ?
            new ObjectParameter("ActivityTypeID", activityTypeID) :
            new ObjectParameter("ActivityTypeID", typeof(int));

        var fileAsParameter = fileAs != null ?
            new ObjectParameter("FileAs", fileAs) :
            new ObjectParameter("FileAs", typeof(string));

        var startTimeParameter = startTime.HasValue ?
            new ObjectParameter("StartTime", startTime) :
            new ObjectParameter("StartTime", typeof(System.DateTime));

        var durationParameter = duration.HasValue ?
            new ObjectParameter("Duration", duration) :
            new ObjectParameter("Duration", typeof(int));

        var commentsParameter = comments != null ?
            new ObjectParameter("Comments", comments) :
            new ObjectParameter("Comments", typeof(string));

        var readAfterUpdateParameter = readAfterUpdate.HasValue ?
            new ObjectParameter("ReadAfterUpdate", readAfterUpdate) :
            new ObjectParameter("ReadAfterUpdate", typeof(bool));

        return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<mobileTimeEntryGet_Result>("mobileTimeEntryUpdate", userLoginParameter, iDParameter, projectIDParameter, activityTypeIDParameter, fileAsParameter, startTimeParameter, durationParameter, commentsParameter, readAfterUpdateParameter);
    }

因此存储过程可能会抛出一些错误,我想静默捕获(我打算在一些对象中保存异常细节并将其传递给调用者)。

但是当发生异常时,事务变为null,我无法提交它。

有人可以建议 - 这种行为的原因是什么?它是如何避免的?感谢

更新

这是堆栈跟踪:

System.Data.Entity.Core.EntityCommandExecutionException:Произошлаошибкапривыполненииопределениякоманды。这是一个很好的选择。 ---&GT; System.Data.SqlClient.SqlException:#accessdenied 交易在触发器中结束。批次已中止。    System.Data.SqlClient.SqlConnection.OnError(SqlException异常,Boolean breakConnection,Action 1 wrapCloseInAction) в System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action 1 wrapCloseInAction)    System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj,Boolean callerHasConnectionLock,Boolean asyncClose)    System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior,SqlCommand cmdHandler,SqlDataReader dataStream,BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject stateObj,Boolean&amp; dataReady)    System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()    System.Data.SqlClient.SqlDataReader.get_MetaData()    System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds,RunBehavior runBehavior,String resetOptionsString,Boolean isInternal,Boolean forDescribeParameterEncryption)    System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior,RunBehavior runBehavior,Boolean returnStream,Boolean async,Int32 timeout,Task&amp; task,Boolean asyncWrite,Boolean inRetry,SqlDataReader ds,Boolean describeParameterEncryptionRequest)    System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior,RunBehavior runBehavior,Boolean returnStream,String method,TaskCompletionSource 1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry) в System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) в System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) в System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) в System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior) в System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.<Reader>b__c(DbCommand t, DbCommandInterceptionContext 1 c)    System.Data.Entity.Infrastructure.Interception.InternalDispatcher 1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func 3操作,TInterceptionContext interceptionContext,Action 3 executing, Action 3执行)    System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.Reader(DbCommand命令,DbCommandInterceptionContext interceptionContext)    System.Data.Entity.Internal.InterceptableDbCommand.ExecuteDbDataReader(CommandBehavior behavior)    System.Data.Common.DbCommand.ExecuteReader(CommandBehavior行为)    System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand,CommandBehavior behavior)    ---Конецтрассировкивнутреннегостекаисключений---    System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand,CommandBehavior behavior)    System.Data.Entity.Core.Objects.ObjectContext.CreateFunctionObjectResult [TElement](EntityCommand entityCommand,ReadOnlyCollection 1 entitySets, EdmType[] edmTypes, ExecutionOptions executionOptions) в System.Data.Entity.Core.Objects.ObjectContext.<>c__DisplayClass47 1.b__46()    System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction [T](Func 1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess) в System.Data.Entity.Core.Objects.ObjectContext.<>c__DisplayClass47 1.b__45()    System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute [TResult](Func 1 operation) в System.Data.Entity.Core.Objects.ObjectContext.ExecuteFunction[TElement](String functionName, ExecutionOptions executionOptions, ObjectParameter[] parameters) в System.Data.Entity.Core.Objects.ObjectContext.ExecuteFunction[TElement](String functionName, MergeOption mergeOption, ObjectParameter[] parameters) в System.Data.Entity.Core.Objects.ObjectContext.ExecuteFunction[TElement](String functionName, ObjectParameter[] parameters) в ******.Entities.mobileTimeEntryUpdate(String userLogin, Nullable 1 iD,Nullable 1 projectID, Nullable 1 activityTypeID,String fileAs,Nullable 1 startTime, Nullable 1 duration,String comments,Nullable `1 readAfterUpdate)Ÿ****** \ DbModel.Context.cs:строка186    в******。Entities.DocumentUpdateForSync(String userLogin,IEntrySync document)в******* \ Entities.cs:строка125

2 个答案:

答案 0 :(得分:1)

假设SQL Server,某些错误将导致事务或回滚事务。请参阅此经典(但仍然相关)的文章Error Handling in SQL 2000 – a Background

答案 1 :(得分:0)

哦,对不起,我必须仔细阅读异常消息 - &#34;交易在触发器中结束&#34; - 这意味着存储过程对调用触发器的表进行了一些更改。而这个触发器由于某些逻辑回滚了事务。我认为这是所述行为的原因。