.NET 6+EF 6+Oracle中执行策略与连接弹性实现位置及用法咨询
.NET 6 + EF 6 + Oracle 连接弹性与执行策略实践方案
一、连接弹性代码的正确放置位置
EF 6的连接弹性(执行策略)是绑定到DbContext的数据库配置,而非仓储层。仓储层仅负责调用DbContext的业务方法,重试逻辑由EF框架层面统一处理,能确保所有通过该DbContext的数据库操作自动应用重试策略,避免在每个仓储方法中重复编写逻辑。
有两种标准配置方式:
- 在DbContext的
OnConfiguring方法中配置(即你提供的代码所在位置) - 在IOC容器注册DbContext时配置(更贴合.NET 6依赖注入的最佳实践)
二、配置Oracle专属执行策略
EF 6默认执行策略主要适配SQL Server,Oracle的连接异常类型不同,需自定义重试逻辑识别Oracle专属错误:
1. 定义Oracle执行策略类
public class OracleExecutionStrategy : DbExecutionStrategy { public OracleExecutionStrategy(int maxRetryCount, TimeSpan maxDelay) : base(maxRetryCount, maxDelay) { } protected override bool ShouldRetryOn(Exception ex) { // 识别Oracle连接相关异常,匹配常见连接池/超时错误码 if (ex is OracleException oracleEx) { var retryErrorCodes = new[] { 12170, 12514, 12541, 12535, 12543, 1033 }; return retryErrorCodes.Contains(oracleEx.Number); } // 兼容通用网络超时异常 return ex is SocketException || ex is TimeoutException; } }
2. 配置到DbContext
方式1:在你提供的OnConfiguring方法中添加
直接修改现有代码,追加执行策略配置:
protected override void OnConfiguring(DbContextOptionsBuilder builder) { base.OnConfiguring(builder.UseOracle(base._connString) .EnableSensitiveDataLogging(true) // 配置重试策略:最大3次重试,每次间隔2秒 .UseExecutionStrategy(() => new OracleExecutionStrategy(3, TimeSpan.FromSeconds(2)))); }
方式2:IOC注册时配置(推荐)
如果DbContext在Program.cs中通过DI注册,代码示例:
builder.Services.AddDbContext<YourDbContext>(options => { options.UseOracle(Configuration.GetConnectionString("OracleConn")) .EnableSensitiveDataLogging(true) .UseExecutionStrategy(() => new OracleExecutionStrategy(3, TimeSpan.FromSeconds(2))); });
三、用执行策略执行存储过程
仓储层调用存储过程时,需将操作包裹在执行策略中,确保异常触发重试:
方式1:无返回值存储过程
public class YourRepository { private readonly YourDbContext _dbContext; private readonly DbExecutionStrategy _executionStrategy; public YourRepository(YourDbContext dbContext) { _dbContext = dbContext; // 从DbContext获取已配置的执行策略 _executionStrategy = _dbContext.Database.CreateExecutionStrategy(); } public void RunYourStoredProcedure(int param1, string param2) { _executionStrategy.Execute(() => { var sql = "BEGIN YOUR_STORED_PROCEDURE(:p1, :p2); END;"; _dbContext.Database.ExecuteSqlCommand(sql, new OracleParameter("p1", param1), new OracleParameter("p2", param2)); }); } }
方式2:有返回实体的存储过程
public List<YourEntity> GetDataFromProc(int param) { return _executionStrategy.Execute(() => { var objectContext = ((IObjectContextAdapter)_dbContext).ObjectContext; return objectContext.ExecuteFunction<YourEntity>("YOUR_STORED_PROCEDURE", new ObjectParameter("p_param", param)).ToList(); }); }
内容的提问来源于stack exchange,提问作者lrobinsonjr
相关产品推荐
相关产品推荐

