Entity Framework Core 中,`CreateExecutionStrategy()

 

在 Entity Framework Core 中,`CreateExecutionStrategy()` 用于创建 **执行策略(Execution Strategy)**,其核心目的是处理数据库操作的 **暂时性故障(Transient Failures)**,例如网络波动、数据库连接中断、死锁等瞬时错误。这一机制尤其在云环境(如 Azure SQL)或高并发场景中至关重要,能显著提升应用程序的 **容错能力** 和 **健壮性**。

---

### **1. 执行策略的作用**
执行策略通过以下方式工作:
- **自动重试**:当检测到 **可重试的异常**(如 `SqlException` 且错误码标识为暂时性错误)时,自动重新执行操作。
- **事务一致性**:在重试过程中确保事务的完整性和一致性,避免数据部分提交。
- **灵活配置**:支持自定义重试次数、重试间隔和异常过滤条件。

例如,SQL Server 的默认执行策略(`SqlServerRetryingExecutionStrategy`)会针对常见的暂时性错误(如错误号 `40613`、`40197`)自动重试操作。

---

### **2. 为什么在事务代码中需要执行策略?**
在事务操作中,数据库连接可能因瞬时故障中断,导致事务失败。如果直接使用简单的事务代码(如 `BeginTransaction` 和 `Commit`),这些错误可能导致整个操作不可恢复。执行策略通过以下方式优化事务处理:

#### **场景示例**
假设以下代码没有执行策略:
```csharp
using var transaction = await _dbContext.BeginTransactionAsync();
try
{
    // 操作1:更新订单状态
    await _dbContext.SaveChangesAsync();

    // 操作2:扣减库存
    await _dbContext.SaveChangesAsync();

    await transaction.CommitAsync();
}
catch (Exception ex)
{
    await transaction.RollbackAsync();
    throw;
}
```
- **问题**:如果 `操作2` 执行时发生暂时性错误(如网络抖动),整个事务会回滚,但不会自动重试。用户需要手动重新提交请求。
- **解决**:通过执行策略包裹事务代码,自动重试整个事务逻辑。

---

### **3. 执行策略与事务的协作**
在您提供的代码中:
```csharp
var strategy = _dbContext.Database.CreateExecutionStrategy();
await strategy.ExecuteAsync(async () =>
{
    using (var transaction = await _dbContext.BeginTransaction())
    {
        await next(); // 执行业务操作(可能包含多次 SaveChanges)

        await _dbContext.CommitTransaction(transaction);
    }
});
```
- **关键点**:
  1. **事务包裹在策略中**:执行策略会确保整个事务块(`BeginTransaction` → 业务操作 → `Commit`)在遇到可重试错误时自动重试。
  2. **重试的原子性**:每次重试会重新创建事务,确保每次尝试是独立的,避免残留状态。
  3. **幂等性要求**:业务操作需设计为幂等(即重试不会导致重复副作用),例如通过唯一约束或幂等令牌。

---

### **4. 执行策略的典型配置**
在 EF Core 中,执行策略通常通过 `DbContextOptionsBuilder` 配置:
```csharp
services.AddDbContext<MyDbContext>(options =>
    options.UseSqlServer(
        connectionString,
        options => options.EnableRetryOnFailure(
            maxRetryCount: 5,
            maxRetryDelay: TimeSpan.FromSeconds(30),
            errorNumbersToAdd: null
        )
    )
);
```
- `EnableRetryOnFailure`:启用 SQL Server 的默认重试策略。
- `maxRetryCount`:最大重试次数。
- `maxRetryDelay`:重试之间的最大延迟。

---

### **5. 代码中为何需要显式调用 `CreateExecutionStrategy()`?**
默认情况下,执行策略已通过 `EnableRetryOnFailure` 启用,但在以下场景需手动调用 `CreateExecutionStrategy()`:
- **需要自定义事务边界**:当业务逻辑需要显式控制事务范围时(如跨多个 `SaveChanges` 或混合 EF 与非 EF 操作)。
- **手动触发重试逻辑**:例如在 MediatR 的管道行为(Pipeline Behavior)中统一封装事务和重试逻辑(如您提供的代码)。

---

### **6. 执行策略的注意事项**
- **事务作用域**:执行策略必须包裹整个事务(包括 `BeginTransaction` 和 `Commit`),否则重试时可能因事务未重置而失败。
- **避免副作用**:确保事务内的操作是幂等的,避免重试导致重复执行(如发送邮件、调用外部 API)。
- **上下文状态**:重试时,`DbContext` 的跟踪实体状态会被重置,需确保每次重试操作是完整的(例如重新加载数据)。

---

### **总结**
在您的代码中,`CreateExecutionStrategy()` 的作用是:
1. **容错保障**:自动重试因暂时性故障失败的事务操作。
2. **事务完整性**:确保事务块在重试时保持原子性。
3. **统一管理**:在 MediatR 管道中集中处理事务和重试逻辑,提升代码可维护性。

如果未使用执行策略,瞬时错误可能导致事务直接失败,需要客户端手动重试,降低系统可靠性。

  

posted on 2025-02-05 20:57  是水饺不是水饺  阅读(125)  评论(0)    收藏  举报

导航