You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否对EF Core ChangeTracker状态快照并按需重置?

EF Core:能否为ChangeTracker生成状态快照并重置?

请问是否可以对EF Core的ChangeTracker当前状态生成快照,并在需要时重置至该快照状态?

假设我们希望实现如下代码逻辑:

public async Task ExecuteTransactionAsync(DbContext context)
{
    var executionStrategy = new SqlServerRetryingExecutionStrategy(context);
    var retries = 0;
    var snapshot = null;

    await executionStrategy.ExecuteAsync(async () =>
    {
        var txOptions = new TransactionOptions
        {
            IsolationLevel = IsolationLevel.ReadCommitted
        };
        using var transaction = new TransactionScope(TransactionScopeOption.RequiresNew, txOptions, TransactionScopeAsyncFlowOption.Enabled)

        if (retries > 0 && snapshot != null)
        {
            // 该方法实际不存在
            context.ChangeTracker.ResetToSnapshot(snapshot);
        }
        // 该方法实际不存在
        var snapshot = context.ChangeTracker.TakeSnapshot();

        retries += 1;
        
        // 假设我们在context上执行插入操作
        context.DoInsert();

        await context.SaveChangesAsync(false);

        // 假设我们在context上执行更新操作
        context.DoUpdate();

        // 假设第一次调用SaveChanges失败,事务会重试
        await context.SaveChangesAsync(false);

        transaction.Complete();
    }
}

该功能的实用性

在结合ChangeTracker和重试事务使用时,数据库会在重试间隙回滚事务,但ChangeTracker没有对应的回滚机制。使用SaveChanges(false)虽能在重试间保留ChangeTracker状态,但会引发以下问题:

  • 首次运行插入实体,重试时会再次添加实体,最终数据库插入两个实体,与预期不符;
  • 若对实体属性使用+=/-=操作(比如Price初始为10,执行Price -=2),重试后Price会变为6,而非预期的8。

因此,能够将ChangeTracker重置至某一时刻的状态极为必要。

以下是未使用快照重置时的问题示例:

public async Task ExecuteTransactionAsync(DbContext context)
{
    var executionStrategy = new SqlServerRetryingExecutionStrategy(context);

    await executionStrategy.ExecuteAsync(async () =>
    {
        var txOptions = new TransactionOptions
        {
            IsolationLevel = IsolationLevel.ReadCommitted
        };
        using var transaction = new TransactionScope(TransactionScopeOption.RequiresNew, txOptions, TransactionScopeAsyncFlowOption.Enabled)

        // 第一次重试时,ChangeTracker中已经添加了一个新实体
        // DoInsert会再添加一个,最终会有两个新实体,与预期的一个不符
        context.DoInsert();

        await context.SaveChangesAsync(false);

        context.DoUpdate();

        // 假设第一次调用SaveChanges失败,事务会重试
        await context.SaveChangesAsync(false);

        transaction.Complete();
    }
}

内容的提问来源于stack exchange,提问作者mcvyty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 15:55:25