c# - EntityFramework:发生异常时,Database.CurrentTransaction 变为 null
问题描述
今天我遇到了实体框架的奇怪问题。考虑以下课程:
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.OnError(SqlException异常,布尔breakConnection,操作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& 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&任务, 布尔 asyncWrite, 布尔 inRetry, SqlDataReader ds, 布尔 describeParameterEncryptionRequest) в System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String 方法, TaskCompletionSource1 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,Action3 executing, Action
3 已执行) - System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.Reader(DbCommand 命令,DbCommandInterceptionContext 拦截上下文) - System.Data.Entity.Internal.InterceptableDbCommand.ExecuteDbDataReader(CommandBehavior 行为) - 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,ReadOnlyCollection1 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文件) в *******\Entities.cs:строка 125
解决方案
假设使用 SQL Server,一些错误将导致事务失败或回滚。请参阅此经典(但仍然相关)文章SQL 2000 中的错误处理 – 背景。
推荐阅读
- javascript - onclick 事件侦听器无法正常工作
- python-3.x - 引用类常量 Python 3
- python - 如何在 Python 中将 JSON 帖子正文写入文件
- hashicorp-vault - Hashicorp Vault 错误“组”,在令牌中找不到声明
- html - 空白:正常与空白:前行
- php - array_key_exists() 期望参数 2 是数组,给定 null - Cakephp 3
- azure - 以编程方式动态生成 Azure Function 的访问代码
- python-3.x - 如何使用 Python 解释自相关和偏自相关图
- ruby-on-rails - 使用 Rspec 执行 Web 请求时的存根控制器方法
- .net - eShopOnContainer - Docker:Visual Studio 在尝试加载 SPA Web App 时给出 404 Page not found 异常异常