是否应在本地SQL Server中使用SqlAzureExecutionStrategy?
关于SqlAzureExecutionStrategy在本地SQL Server的使用建议
首先看你贴出的死锁异常堆栈:
System.Data.Entity.Core.EntityException: 已引发可能由瞬态故障导致的异常。如果您连接的是SQL Azure数据库,请考虑使用SqlAzureExecutionStrategy。 ---> System.Data.Entity.Core.UpdateException: 更新条目时出错。请查看内部异常了解详细信息。 ---> System.Data.SqlClient.SqlException: 事务(进程ID 65)与另一个进程在锁资源上发生死锁,已被选为死锁牺牲品。请重新运行该事务。 ved System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) ved System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) ved System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) ved System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, Boolean isInternal, Boolean forDescribeParameterEncryption, Boolean shouldCacheForAlwaysEncrypted) ved System.Data.SqlClient.SqlCommand.CompleteAsyncExecuteReader(Boolean isInternal, Boolean forDescribeParameterEncryption) ved System.Data.SqlClient.SqlCommand.InternalEndExecuteNonQuery(IAsyncResult asyncResult, String endMethod, Boolean isInternal) ved System.Data.SqlClient.SqlCommand.EndExecuteNonQueryInternal(IAsyncResult asyncResult) ved System.Data.SqlClient.SqlCommand.EndExecuteNonQueryAsync(IAsyncResult asyncResult) ved System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
针对你关心的SqlAzureExecutionStrategy是否适用于本地SQL Server这个问题,我可以明确给出结论:
虽然名字里带"Azure",但它确实可以用于本地SQL Server环境。EF官方文档提到的"执行策略2和4"其实就是指
SqlAzureExecutionStrategy(以及它的异步版本SqlAzureAsyncExecutionStrategy),它们包含在EntityFramework.SqlServer程序集里,本质是为SQL Server系列产品设计的,自然包括本地实例。这个策略的核心作用是自动重试符合瞬态故障特征的数据库操作,你遇到的死锁异常就属于它会处理的重试场景之一。所以即使是本地SQL Server,当你遇到这类需要重试的瞬态错误时,启用它是完全合理的。
不过有几点需要注意:
- 确保你的EF版本是EF6及以上,这个策略是从EF6开始引入的
- 启用执行策略后,EF会自动将所有操作包装在事务中(因为重试需要保证操作的幂等性),所以要确保你的业务逻辑是幂等的,避免重试导致重复执行带来的问题
- 你已经配置了
READ COMMITTED SNAPSHOT,这确实能减少死锁发生的概率,但无法完全避免,配合执行策略的重试机制是很好的补充方案
具体启用的方式很简单,在你的DbContext类里重写OnConfiguring方法即可:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer("你的数据库连接字符串", options => options.ExecutionStrategy(c => new SqlAzureExecutionStrategy(c))); }
总结一下:SqlAzureExecutionStrategy的命名确实容易让人产生误解,但它完全适用于本地SQL Server,针对你遇到的死锁问题,启用它来自动重试事务是一个有效的解决方案。
内容的提问来源于stack exchange,提问作者Robert Jørgensgaard Engdahl
相关产品推荐
相关产品推荐

