.NET Core中ExecuteSqlRawAsync忽略执行策略,如何注入错误处理?
解决EF Core中存储过程调用无法触发执行策略的问题
直接使用Database.ExecuteSqlRawAsync调用存储过程时,确实不会自动纳入EF Core执行策略的错误处理逻辑(重试、日志等),因为这类原始SQL操作默认不会走执行策略的包裹流程。以下是几种可行的解决办法:
1. 手动用执行策略包裹存储过程调用
从DbContext获取执行策略实例,将存储过程的调用逻辑包裹在执行策略的ExecuteAsync方法中,这样就能让执行策略接管错误处理:
var executionStrategy = Database.CreateExecutionStrategy(); await executionStrategy.ExecuteAsync(async () => { await Database.ExecuteSqlRawAsync("exec dbo.spDoMyVeryTailoredProcedure"); });
2. 封装通用方法减少重复代码
由于你有几十个存储过程调用,可以在DbContext中封装一个通用方法,统一处理执行策略的包裹,避免重复编写相同逻辑:
public async Task ExecuteSpWithStrategyAsync(string spSql, params object[] parameters) { var strategy = Database.CreateExecutionStrategy(); await strategy.ExecuteAsync(async () => { await Database.ExecuteSqlRawAsync(spSql, parameters); }); }
之后所有存储过程调用都替换为这个方法:
await ExecuteSpWithStrategyAsync("exec dbo.spDoMyVeryTailoredProcedure"); // 带参数的情况 await ExecuteSpWithStrategyAsync("exec dbo.spAnotherProcedure @Param1 = {0}", paramValue);
3. 确认执行策略已正确配置
确保在配置DbContext时已经启用了SQL Server的重试执行策略,否则上述包裹逻辑不会生效:
services.AddDbContext<YourDbContext>(options => options.UseSqlServer( connectionString, sqlOpts => sqlOpts.EnableRetryOnFailure( maxRetryCount: 5, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null) ) );
4. 自定义执行策略(按需使用)
如果默认的重试策略无法满足你的业务需求(比如需要针对特定异常类型重试、添加自定义日志),可以自定义执行策略类,然后在配置DbContext时指定使用:
public class CustomSqlExecutionStrategy : SqlServerRetryingExecutionStrategy { public CustomSqlExecutionStrategy( DbContext context, int maxRetryCount, TimeSpan maxRetryDelay, ICollection<int>? errorNumbersToAdd) : base(context, maxRetryCount, maxRetryDelay, errorNumbersToAdd) { } protected override bool ShouldRetryOn(Exception exception) { // 在这里添加自定义的重试判断逻辑 return base.ShouldRetryOn(exception) || exception is YourCustomException; } protected override Task<ExecutionResult> ExecuteAsync<TState>( Func<DbContext, TState, Task<ExecutionResult>> operation, Func<DbContext, TState, Task<ExecutionResult>> verifySucceeded, TState state, DbContext context, CancellationToken cancellationToken) { // 执行前后可以添加自定义日志逻辑 return base.ExecuteAsync(operation, verifySucceeded, state, context, cancellationToken); } }
配置时指定使用自定义策略:
services.AddDbContext<YourDbContext>(options => options.UseSqlServer(connectionString) .ReplaceService<IExecutionStrategy, CustomSqlExecutionStrategy>());
内容的提问来源于stack exchange,提问作者Nomenator
相关产品推荐
相关产品推荐

