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

更新实体时如何忽略报错记录,处理包含内部异常详情的错误

问题解决:实体更新时跳过错误记录仅保存合法数据

问题根因

你当前的实现逻辑是先将所有待写入的PAY实体全部添加到DbContext的跟踪集合,再统一调用SaveChanges()。EF默认会把本次所有写入操作封装到同一个事务中,任意一条数据触发数据库约束报错、实体校验失败,都会触发全局事务回滚,导致全部数据都无法入库。

最优实现方案(易上手、逻辑清晰)

采用逐行提交+错误隔离的逻辑:每次添加一条实体后就尝试提交,提交失败则将当前错误实体从Context的跟踪列表中移除,记录错误后继续处理下一条数据。如果数据量较大(超过1000条),可以调整为分批提交(如每20条提交一次,失败则拆分当前批次逐行校验),平衡性能与容错能力。

修改后的完整代码

private void btn_salary_Click(object sender, EventArgs e)
{
    if (sg.HasRows(lib.tbl_pay) == true && chkShowOnly.Checked == false)
    {
        lib.ShowMessage(lib.tbl_pay + " has data can not import");
        return;
    }
    sql = "SELECT * FROM PAY WHERE BankAc IS NOT null";
    q1 = new DBFHelper(txt_olddir.Text).FillDataTable(sql);
    dataGridView1.DataSource = q1;
    if (chkShowOnly.Checked == true) return;
    DateTime xdate = sg.ServerDate;
    // 新增计数变量,分别统计成功、失败条数
    int successCount = 0;
    int failCount = 0;
    for (int x = 0; x < q1.Rows.Count; x++)
    {
        PAY q11 = new PAY
        {
            BANKAC = sg.AsString(q1.Rows[x]["BankAc"]),
            MDATE = sg.AsDate(q1.Rows[x]["MDATE"].ToString()),
            BYEAR = sg.AsDate(q1.Rows[x]["MDATE"].ToString()).Year,
            BMONTH = sg.AsDate(q1.Rows[x]["MDATE"].ToString()).Month,
            PERPAY = q1.AsDecimal("PERPAY", x),
            BASIC = q1.AsDecimal("PERPAY", x),
            DARATE = q1.AsDecimal("DA", x),
            NEWDA = q1.AsDecimal("NEWDA",x),
            ADNDA = q1.AsDecimal ("ADNDA",x),
            HRA = q1.AsDecimal ("HRA",x),
            ENTREL = q1.AsDecimal("ENTREL",x),
            EXTRA = q1.AsDecimal("EXTRA",x),
            INSKNP = q1.AsDecimal("INSGKP",x),
            MEDI = q1.AsDecimal("MEDI",x),
            RD = q1.AsDecimal("RD",x),
            GPF = q1.AsDecimal("GPF",x),
            GPFLOAN= q1.AsDecimal("GPFLOAN",x),
            CPF = q1.AsDecimal("CPF",x),
            CPFLOAN = q1.AsDecimal("CPFLOAN",x),
            LICPRE = q1.AsDecimal("LICPRE",x),
            LICLOAN = q1.AsDecimal("LICLOAN",x),
            ITAX = q1.AsDecimal("ITAX",x),
            JSBLOAN = q1.AsDecimal("JSBLOAN",x),
            NSBLOAN = q1.AsDecimal("NSBLOAN",x),
            STEMP = q1.AsDecimal("STEMP",x),
            PROFUND = q1.AsDecimal("PROFUND",x),
            TYPE_ATX = q1.AsString("TYPE",x),
            GRADE = q1.AsString("GRADE",x),
            TFUND = q1.AsDecimal("TFUND",x),
            GFUND = q1.AsDecimal("GFUND",x),
            OBCLOAN = q1.AsDecimal("OBCLOAN",x),
            OTH1_LOAN = q1.AsDecimal("OTH1_LOAN",x),
            OTH2_LOAN = q1.AsDecimal("OTH2_LOAN",x),
            BSTGBANK = q1.AsDecimal("BSTGBANK",x),
            EARNING = q1.AsDecimal("EARNING",x),
            TOTDED = q1.AsDecimal("TOTDED",x),
            NETPAY = q1.AsDecimal("NETPAY",x),
            CITYALW = q1.AsDecimal("CITYALW",x),
            user_code = lib.user_code,
            modi_dt = xdate
        };
        g1.PAYs.Add(q11);
        try
        {
            // 单条提交,成功则计数+1
            g1.SaveChanges();
            successCount++;
            lbl_counter.Text = $"{successCount} 条记录已插入,{failCount} 条插入失败";
            Application.DoEvents();
        }
        catch (Exception ex)
        {
            failCount++;
            // 关键:将错误实体从上下文跟踪中移除,避免影响后续其他数据提交
            g1.Entry(q11).State = EntityState.Detached;
            // 拼接全量错误信息
            string emsg = $"第{x+1}条记录插入失败:";
            Exception innerEx = ex;
            while (innerEx != null)
            {
                emsg += innerEx.Message;
                innerEx = innerEx.InnerException;
            }
            // 可根据需求选择弹窗提示/写入日志,不需要单条弹窗可以注释下行,最后统一汇总提示
            lib.ShowMessage(emsg);
        }
    }
    lib.ShowMessage($"处理完成:共{q1.Rows.Count}条数据,成功插入{successCount}条,失败{failCount}条");
}

优化建议

  • 建议新增前置校验逻辑:在构造PAY实体前就检查字段合法性,比如MDATE是否能正常转为日期、数值字段是否为合法数字、必填字段是否为空,提前筛除错误数据,效率远高于触发数据库报错后再回滚。
  • 如果数据量超过1000条,建议改为分批提交:比如每20条提交一次,提交失败再将当前批次逐条校验提交,减少数据库交互次数提升性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 00:24:03