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

SqlServerRetryingExecutionStrategy不支持用户发起事务的原因及SQL Server 2014适配方案

问题解答

报错是否和SQL Server版本相关

这个报错本质是EF Core的SqlServerRetryingExecutionStrategy的内置限制,SQL Server版本差异是触发条件而非根本原因:

  • EF Core的重试执行策略默认会校验用户手动开启的事务,避免重试时出现事务状态不一致的问题
  • SQL Server 2019及更高版本支持更高版本的TDS协议和透明事务重试逻辑,该校验逻辑在高版本SQL Server下不会被触发,所以你本地运行正常;SQL Server 2014不支持对应特性,就会触发校验抛出报错

修复方案

  • 首先修正代码核心bug:你在using块中实例化了posDbCtx上下文、开启了事务,但所有数据库操作(Add、SaveChanges)都使用了外部的_posDbContext实例,两个上下文完全独立,事务根本没生效,这也是触发报错的核心原因之一
  • 把两个相关的数据库操作合并到同一个执行策略执行块中,所有操作都使用当前块内的上下文实例,避免跨上下文操作事务

正确代码示例:

using(var posDbCtx = new PosDbContext())
{
    var strategy = posDbCtx.Database.CreateExecutionStrategy();
    // 所有事务逻辑都放在Execute的回调内
    strategy.Execute(() =>
    {
        using (var transaction = posDbCtx.Database.BeginTransaction())
        {
            // 所有操作都用当前块内的posDbCtx,不要混用外部上下文
            posDbCtx.PrintJobs.Add(_printJobs);
            posDbCtx.SaveChanges();

            int lineindex = 0;
            foreach (var jline in _printjoblines)
            {
                var pjobline = new PrintJobLine
                {
                    PrintLineId = Guid.NewGuid(),
                    PrintJobId = jline.PrintJobId,
                    LineIndex = lineindex,
                    Text = jline.Text,
                    RightText = jline.RightText,
                    LeftText = jline.LeftText,
                    LineLength = jline.LineLength,
                    PrintOptions = jline.PrintOptions,
                    ItemName = jline.ItemName,
                    Quantity = jline.Quantity,
                    Flags = jline.Flags,
                    BergPlu = jline.BergPlu,
                    ActualPrice = jline.ActualPrice,
                    BasePrice = jline.BasePrice,
                    Vducolor = jline.Vducolor,
                    ParentIndex = jline.ParentIndex,
                    Peplu = jline.Peplu,
                    SaleItemId = jline.SaleItemId,
                    SaleTenderId = jline.SaleTenderId,
                    SignatureId = jline.SignatureId
                };
                posDbCtx.PrintJobLines.Add(pjobline);
                lineindex++;   
            }
            // 批量提交即可,不需要循环内每次调用SaveChanges,可大幅提升性能
            posDbCtx.SaveChanges();
            transaction.Commit();
        }
    });
}

补充说明

  • 如果你两个操作确实不需要在同一个事务内,可以分开写,但每个执行策略块内部都必须使用当前块内实例化的上下文操作,不能混用外部上下文
  • 如果你的业务场景不需要重试策略,可以在DbContext的配置中移除EnableRetryOnFailure配置,也可以规避这个报错,但更推荐按照上述正确写法使用重试策略,提升弱网环境下的操作成功率

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 02:24:03