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

Entity Framework SaveChanges()回滚:批量插入异常时回滚状态与人员数据

问题解答

当前代码无法回滚已保存至State表和Peoples表的数据

原因分析

  • State数据的保存操作context.SaveChanges();在插入人员数据之前就已执行,且该操作未被任何事务包裹,执行后数据直接持久化到数据库,无法回滚。
  • 每个州的处理逻辑都在独立的StateEntities上下文实例中,EF默认事务仅覆盖单次SaveChanges操作,State保存完成后就脱离了事务控制。
  • InsertPeople方法中的TransactionScope仅对当前批次的人员插入生效,每次批次完成后调用transactionScope.Complete()提交事务,之前批次的人员数据已经持久化;若后续批次抛出异常,只能回滚当前正在处理的批次,无法影响已提交的批次和State数据。

修改方案

要实现State数据和对应所有人员数据的原子性操作(要么全部成功,要么全部回滚),需要将State的保存和该州所有人员的插入操作纳入同一个事务范围内。以下是调整后的代码示例:

List<Peoples> PeopleList = new List<Peoples>();
int peopleCounter = 0;

foreach (var stateVal in States)
{
    // 为每个州创建全局事务范围
    using (var transactionScope = new TransactionScope(TransactionScopeOption.Required, new System.TimeSpan(0, 60, 0)))
    {
        using (var context = new StateEntities())
        {
            State st = new State();
            st.ID = stateVal.ID;
            st.Name = stateVal.Name;

            context.State.Add(st);
            context.SaveChanges(); // 此时操作处于事务范围内,未真正提交

            if (stateVal.Peoples != null)
            {
                foreach (var _p in stateVal.Peoples)
                {
                    Peoples _people = new Peoples();
                    _people.Name = _p.Name;
                    _people.Age = _p.Age;
                    _people.State_ID = stateVal.ID;

                    PeopleList.Add(_people);
                    peopleCounter++;

                    if (peopleCounter == 100000)
                    {
                        InsertPeople(PeopleList, context);
                        PeopleList.Clear();
                        peopleCounter = 0;
                    }
                }
                // 处理剩余不足100k的人员数据
                if (PeopleList.Count > 0)
                {
                    InsertPeople(PeopleList, context);
                    PeopleList.Clear();
                    peopleCounter = 0;
                }
            }
        }
        // 所有操作完成后提交事务
        transactionScope.Complete();
    }
}

private static void InsertPeople(List<Peoples> PeopleList, StateEntities context)
{
    context.Configuration.AutoDetectChangesEnabled = false;
    context.Configuration.ValidateOnSaveEnabled = false;

    // 不再需要单独的TransactionScope,因为上下文已处于外层事务范围内
    context.BulkInsert(PeopleList, options => options.BatchTimeout = 0);
    context.SaveChanges();
}

关键调整说明

  • 将每个州的完整操作(State保存+所有人员插入)包裹在同一个TransactionScope中,确保所有操作要么全部提交,要么全部回滚。
  • 移除InsertPeople方法内的独立事务,让批量插入操作继承外层的事务上下文。
  • 补充处理循环结束后剩余的不足100k的人员数据,避免遗漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 23:54:28