Oggi ho affrontato strani problemi con Entity Framework. Considera la seguente classe:
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();
}
}
Questa classe fa parte della classe autogenerata, creata da EF. Si eredita dalla classe DbContext. Il metodo mobileTimeEntryUpdate è un wrapper generato automaticamente per la stored procedure:
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);
}
Quindi la stored procedure può generare alcuni errori, che voglio prendere in silenzio (ho intenzione di salvare i dettagli delle eccezioni in alcuni oggetti e passarli al chiamante).
Ma quando si verifica un'eccezione, la transazione diventa nulla e non posso eseguirla.
Qualcuno può suggerire: qual è la causa di tale comportamento? E come può essere evitato? Grazie
Aggiornare
Ecco la traccia dello stack:
System.Data.Entity.Core.EntityCommandExecutionException: ÐŸÑ € оиР· оÑÐ »Ð ° оÑиР± кР° Ð¿Ñ € и Ð²Ñ <пол нÐμнии Ð¾Ð¿Ñ € ÐμÐ'ÐμÐ » ÐμÐ½Ð¸Ñ ÐºÐ¾Ð¼Ð ° нÐ'Ñ <. Ð "опол ниÑ,ÐμÐ »ÑŒÐ½Ñ <Ðμ Ñ Ð²ÐμÐ½Ñ <во внуÑ,Ñ € ÐμннÐμм Ð¸Ñ ÐºÐ» ÑŽÑ ‡ Ðμнии. ---> System.Data.SqlClient.SqlException: #accessdenied La transazione è terminata con il trigger. Il lotto è stato interrotto. в System.Data.SqlClient.SqlConnection.OnError (eccezione SqlException, booleano breakConnection, Azione 1 wrapCloseInAction) в System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action
1 wrapCloseInAction) в System.Data.SqlClient.TdsParser .ThrowExceptionAndWarning (stateObj TdsParserStateObject, booleano callerHasConnectionLock, booleano asyncClose) D² System.Data.SqlClient.TdsParser.TryRun (runBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader datastream, bulkCopyHandler BulkCopySimpleResultSet, stateObj TdsParserStateObject, booleano e dataReady) D² 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 cmdB comportamento, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task & task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest) в System.Data.SqlClient.SqlCommand.RunExecuteReader (CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String metodo, 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
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) в Syst em.Data.Entity.Infrastructure.Interception.InternalDispatcher 1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func
Operazione 1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func
3, TInterceptionContext interceptionContext, Azione 3 executing, Action
3 eseguita) в System.Data.Entity.Infrastructure.Interception .DbCommandDispatcher.Reader (comando DbCommand, DbCommandInterceptionContext interceptionContext) в System.Data.Entity.Internal.InterceptableDbCommand.ExecuteDbDataReader (comportamento CommandBehavior) в System.Data.Common.DbCommand.ExecuteReader (comportamento CommandBehavior) в System.Data.Entity.Core. EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands (EntityCommand entityCommand, Comando Comportamento comportamento) --- КонÐμÑ † Ñ,Ñ € Ð ° Ñ Ñ Ð¸Ñ € овки внуÑ,Ñ € ÐμннÐμго Ñ Ñ,ÐμкР° Ð¸Ñ ÐºÐ »ÑŽÑ ‡ Ðμний --- в System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands (EntityCommand enti tyCommand, Comportamento Comportamento) в 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] ( 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
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, documento IEntrySync) в ******* \ Entities.cs: Ñ Ñ,Ñ € окР° 125
Supponendo SQL Server, alcuni errori porteranno o annulleranno la transazione. Vedi questo articolo classico (ma ancora rilevante) Gestione degli errori in SQL 2000 â € "uno sfondo .