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

DbContext SaveChanges遇验证错误,修改数据后仍重复报错

问题描述

通过继承自DbContext的eBusinessEntities实现了CSV数据更新方法,测试错误场景时上传了包含无效State字段的Test.Entry@aol.com数据,收到验证错误:

Test.Entry@aol.com has the following validation errors:-"Field: "State", Error: "The field State must be a string or array type with a maximum length of '2'."

但修复数据后,甚至上传完全不同的新数据(如DifferentEntry@gmail.com)时,仍抛出针对Test.Entry@aol.com的相同验证错误。调试确认当前创建的Entry数据完全匹配CSV内容,但调用SaveChanges()时仍触发旧错误。

相关代码

异常捕获代码

try
{
    var success = _dbContext.SaveChanges() > 0;
    return success ? "Done! Please reload the page" : "Failed to update entries";
}
catch (DbEntityValidationException e)
{
    var output = "FAILED TO SAVE CHANGES TO DATABASE. Please see the following validation errors:<br/>";
    foreach (var eve in e.EntityValidationErrors)
    {
        output += String.Format("{0} has the following validation errors:",
            eve.Entry.Property("Email").CurrentValue);
        foreach (var ve in eve.ValidationErrors)
        {
            output += String.Format("- Field: \"{0}\", Error: \"{1}\"<br/>",
                ve.PropertyName, ve.ErrorMessage);
        }
    }
    return output;
}

仓储层代码

public class EntriesRepository : CachableBase, IEntriesRepository
{
    private readonly IeBusinessEntities _ieBusinessEntities;

    public EntriesRepository(IeBusinessEntities ieBusinessEntities)
    {
        _ieBusinessEntities = ieBusinessEntities;
    }

    public string UpdateEntries(List<Entry> entries)
    {
        foreach (var entry in entries)
        {
              _ieBusinessEntities.Entries.Add(entry);
        }

        // 上述异常捕获代码,此处替换为_dbContext为_ieBusinessEntities
        try
        {
            var success = _ieBusinessEntities.SaveChanges() > 0;
            return success ? "Done! Please reload the page" : "Failed to update entries";
        }
        catch (DbEntityValidationException e)
        {
            var output = "FAILED TO SAVE CHANGES TO DATABASE. Please see the following validation errors:<br/>";
            foreach (var eve in e.EntityValidationErrors)
            {
                output += String.Format("{0} has the following validation errors:",
                    eve.Entry.Property("Email").CurrentValue);
                foreach (var ve in eve.ValidationErrors)
                {
                    output += String.Format("- Field: \"{0}\", Error: \"{1}\"<br/>",
                        ve.PropertyName, ve.ErrorMessage);
                }
            }
            return output;
        }
    }
    // 其他方法...
}
原因分析

DbContext是上下文实例级别的状态跟踪容器:

  • 第一次上传错误数据时,Test.Entry@aol.com对应的Entry实体已被添加到当前DbContext实例的变更跟踪器中,处于Added状态。
  • 即使后续上传新数据,只要使用的是同一个DbContext实例,之前添加的错误实体不会自动被清理。调用SaveChanges()时,DbContext会尝试提交所有处于跟踪状态的实体变更,包括那个未被移除的错误实体,因此会重复触发相同的验证错误。
解决方案

1. 使用独立的DbContext实例(推荐)

将DbContext的生命周期配置为请求域(Scoped)(如果是依赖注入场景),确保每次CSV上传请求都使用全新的DbContext实例,从根源避免旧实体残留。

2. 手动清理上下文残留实体

在UpdateEntries方法处理新数据前,主动移除所有未提交的Entry实体:

public string UpdateEntries(List<Entry> entries)
{
    // 清理所有处于Added状态的Entry实体
    var addedEntries = _ieBusinessEntities.Entries.Local
        .Where(e => _ieBusinessEntities.Entry(e).State == EntityState.Added)
        .ToList();
    foreach (var entry in addedEntries)
    {
        _ieBusinessEntities.Entry(entry).State = EntityState.Detached;
    }

    // 继续添加新数据
    foreach (var entry in entries)
    {
          _ieBusinessEntities.Entries.Add(entry);
    }

    // 后续的SaveChanges和异常捕获逻辑...
}

3. 捕获错误后立即清理错误实体

在DbEntityValidationException捕获块中,将验证失败的实体从上下文跟踪中移除,避免后续提交时再次触发错误:

catch (DbEntityValidationException e)
{
    var output = "FAILED TO SAVE CHANGES TO DATABASE. Please see the following validation errors:<br/>";
    foreach (var eve in e.EntityValidationErrors)
    {
        output += String.Format("{0} has the following validation errors:",
            eve.Entry.Property("Email").CurrentValue);
        foreach (var ve in eve.ValidationErrors)
        {
            output += String.Format("- Field: \"{0}\", Error: \"{1}\"<br/>",
                ve.PropertyName, ve.ErrorMessage);
        }
        // 将错误实体从上下文跟踪中分离
        _ieBusinessEntities.Entry(eve.Entry.Entity).State = EntityState.Detached;
    }
    return output;
}

内容的提问来源于stack exchange,提问作者Erica Stockwell-Alpert

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 13:54:23