EntityFramework: Database.CurrentTransaction становится нулевым, когда происходит исключение - PullRequest
0 голосов
/ 08 мая 2018

Сегодня я столкнулся со странной проблемой с 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);
    }

Таким образом, хранимая процедура может выдавать некоторые ошибки, которые я хочу отловить без вывода сообщений (я планирую сохранить подробности исключения в некотором объекте и передать его вызывающей стороне).

Но когда возникает исключение, транзакция становится нулевой, и я не могу ее зафиксировать.

Может кто-нибудь подсказать - в чем причина такого поведения?И как этого можно избежать?Спасибо

Обновление

Вот трассировка стека:

System.Data.Entity.Core.EntityCommandExecutionException: Произошла ошибка при выполнении определения команды.Дополнительные сведения предоставляются во внутреннем исключении.---> System.Data.SqlClient.SqlException: #accessdenied Транзакция завершилась в триггере.Пакет был прерван.в System.Data.SqlClient.SqlConnection..TdsParser.TryRun (runBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader DATASTREAM, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean и dataReady) в System.Data.SqlClient.SqlDataReader.TryConsumeMetaData () в System.Data.SqlClient.SqlDataReader.get_MetaData () в системе.Data.SqlClient.SqlCommand.FinishExecuteReader (SqlDataReader Д.С., runBehavior runBehavior, String resetOptionsString, Boolean IsInternal, Boolean forDescribeParameterEncryption) в System.Data.SqlClient.SqlCommand.RunExecuteReaderTds (CommandBehavior cmdBehavior, runBehavior runBehavior, Boolean returnStream, Boolean асинхронные, Int32 тайм-аут, задач изадача, логическое asyncWrite, логическое inRetry, SqlDataReader ds, логическое значение descriptionParameterEncryptionRequest) в System.Data.SqlClient.SqlCommand.RunExecuteReader (CommandBehavior cmdBehavior, RunBehavior runBehavior, логический returnStream, метод String, TaskCompletionSternIntern_Inter.* 3 операция, TInterceptionContext interceptionContext, действие 3 executing, Action 3 выполнено) в System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.Reader (команда DbCommand, DbCommandInterceptionContext interceptionContext) в System.Data.Entity.Internal.CommandDeventBextReviewEvent) в System.Data.Common.DbCommand.ExecuteReader (поведение CommandBehavior) в System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands (EntityCommand entityCommand, CommandBehavior,) --- выполнение упражнений дляSystem.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands (EntityCommand entityCommand, поведение CommandBehavior) в System.Data.Entity.Core.Objects.ObjectContext.CreateFunctionObjectResult [TElement] (EntityCommand entityCommand, ReadOnlyColject.Object..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, файл строкиNullable 1 startTime, Nullable 1 длительность, строковые комментарии, Nullable`1 readAfterUpdate) в ****** \ DbModel.Context.cs: строка 186 в ******. Entities.DocumentUpdateForSync (строка userLogin, документ IEntrySync) в******* \ Entities.cs: строка 125

Ответы [ 2 ]

0 голосов
/ 09 мая 2018

Ой, извините, я должен внимательно прочитать сообщение об исключении - «Транзакция завершилась в триггере» - это означает, что хранимая процедура внесла некоторые изменения в таблицы, которые вызвали триггер. И этот триггер из-за некоторой логики отката транзакции. Я думаю, что это является причиной описанного поведения.

0 голосов
/ 08 мая 2018

Предполагая, что SQL Server, некоторые ошибки обрекают или откатывают транзакцию. См. Эту классическую (но все еще актуальную) статью Обработка ошибок в SQL 2000 - фон .

...