C# 在读取时遇到死锁时如何使用实体框架重试策略

C# 在读取时遇到死锁时如何使用实体框架重试策略,c#,.net,entity-framework,C#,.net,Entity Framework,我已经使用Entity Framework(.NET Framework)配置了重试策略,该策略在大多数情况下都可以正常工作。我从未见过它不适用于更新/写入。但我偶尔会遇到一些没有被截获的问题 特别是,我遇到了一个在读取数据时遇到死锁的情况。然后重试机制不起作用,从堆栈跟踪摘录中可以看到: Exception: System.Data.Entity.Core.EntityCommandExecutionException: An error occurred while reading from

我已经使用Entity Framework(.NET Framework)配置了重试策略,该策略在大多数情况下都可以正常工作。我从未见过它不适用于更新/写入。但我偶尔会遇到一些没有被截获的问题

特别是,我遇到了一个在读取数据时遇到死锁的情况。然后重试机制不起作用,从堆栈跟踪摘录中可以看到:

Exception: System.Data.Entity.Core.EntityCommandExecutionException: An error occurred while reading from the store provider's data reader. See the inner exception for details. ---> System.Data.SqlClient.SqlException: Transaction (Process ID 56) was deadlocked on lock | communication buffer resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlDataReader.TryHasMoreRows(Boolean& moreRows)
   at System.Data.SqlClient.SqlDataReader.TryReadInternal(Boolean setTimeout, Boolean& more)
   at System.Data.SqlClient.SqlDataReader.Read()
   at System.Data.Entity.Core.Common.Internal.Materialization.Shaper`1.StoreRead()
   --- End of inner exception stack trace ---
   at System.Data.Entity.Core.Common.Internal.Materialization.Shaper`1.HandleReaderException(Exception e)
   at System.Data.Entity.Core.Common.Internal.Materialization.Shaper`1.StoreRead()
   at System.Data.Entity.Core.Common.Internal.Materialization.Shaper`1.SimpleEnumerator.MoveNext()
   at System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()
这里是导致它的代码的一个等价片段。导致死锁的是foreach中的迭代器,而不是SaveChanges()方法:

使用(var context=new MyContest())
{
var query=context.messages.Where(m=>m.unique\u id==uniqueId);
foreach(查询中的var消息)//
{
if(string.IsNullOrWhiteSpace)返回;
//一些伐木
}
));
SetExecutionStrategy(“System.Data.SqlClient”,()=>newcommonExecutionStrategy());
}
我预计重试和日志截取将启动,并且与成功重试的更新失败类似:

   at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.Reader(DbCommand command, DbCommandInterceptionContext interceptionContext)
   at System.Data.Entity.Core.Mapping.Update.Internal.DynamicUpdateCommand.Execute(Dictionary`2 identifierValues, List`1 generatedValues)
   at System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.Update()
   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.SaveChangesToStore(SaveOptions options, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction)
   at System.Data.Entity.Infrastructure.DbExecutionStrategy.Execute[TResult](Func`1 operation)
   at System.Data.Entity.Core.Objects.ObjectContext.SaveChangesInternal(SaveOptions options, Boolean executeInExistingTransaction)
   at System.Data.Entity.Internal.InternalContext.SaveChanges()

有没有一种方法可以解决这个问题,而不必显式调用执行策略或其他重试机制?

我不确定,但您可以使用名为Polly的库。Polly允许您创建重试策略,首先,它用于重试HTTP类,但您可以创建通用策略,以便能够处理EF请求。您可以添加代码将拦截绑定到EF吗?您看过了吗?谢谢,我看过了。我的shouldRetryOn目前在大多数情况下都返回true,肯定包括死锁。我不确定,但您可以使用名为Polly的库。Polly允许您创建重试策略,首先,它用于重试HTTP类,但您可以创建通用策略,以便能够处理EF请求。您可以添加代码将拦截绑定到EF吗?您看过了吗?谢谢,我看过了。我的shouldRetryOn目前在大多数情况下都返回true,当然也包括死锁。