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

EF Core 7中无法使用DbEntityValidationException的问题求助

EF Core 7迁移:替换DbEntityValidationException及重构Commit方法

以下是适配EF Core 7的完整重构代码:

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Validation;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Configuration;

public void Commit(bool validateSave = true)
{
    ValidationBehavior? validationInterceptor = null;
    try
    {
        // 处理验证开关:当validateSave为false时,临时移除验证拦截器
        if (!validateSave)
        {
            validationInterceptor = DbContext.GetService<IEnumerable<IInterceptor>>()
                .OfType<ValidationBehavior>()
                .FirstOrDefault();
            
            if (validationInterceptor != null)
            {
                DbContext.RemoveInterceptor(validationInterceptor);
            }
        }

        Guid tranId = Guid.Empty;
        List<object> addeds = new List<object>();
        List<Log> modifiedAndDeleteds = new List<Log>();
        Logger logger = new Logger();

        bool logEnabled = Convert.ToBoolean(ConfigurationManager.AppSettings["logEnabled"]);
        if (logEnabled)
        {
            tranId = Guid.NewGuid();
            addeds = DbContext.ChangeTracker.Entries()
                .Where(s => s.State == EntityState.Added)
                .Select(s => s.Entity)
                .ToList();
            
            modifiedAndDeleteds = logger.GetLogsOfNonAddeds(
                DbContext.ChangeTracker.Entries()
                    .Where(s => s.State == EntityState.Modified || s.State == EntityState.Deleted), 
                tranId);
        }

        // 手动验证(当validateSave为true时)
        if (validateSave)
        {
            DbContext.ValidateEntities();
        }

        DbContext.SaveChanges();

        if (logEnabled)
        {
            logger.LogAddeds(addeds, tranId);
            logger.LogNonAddeds(modifiedAndDeleteds);
        }
    }
    catch (DbUpdateException dbEx)
    {
        // 提取验证错误信息
        if (dbEx.InnerException is ValidationException validationEx)
        {
#if DEBUG
            void LogValidationErrors(Exception ex)
            {
                if (ex is ValidationException valEx)
                {
                    if (valEx.ValidationResult != null)
                    {
                        foreach (var memberName in valEx.ValidationResult.MemberNames)
                        {
                            Trace.TraceInformation("Class: {0}, Property: {1}, Error: {2}",
                                valEx.ValidationResult.MemberNames.Any() ? valEx.ValidationResult.MemberNames.First() : "Unknown",
                                memberName,
                                valEx.ValidationResult.ErrorMessage);
                        }
                    }
                    valEx.InnerException?.Let(LogValidationErrors);
                }
            }

            LogValidationErrors(validationEx);
#endif
        }
        throw;
    }
    catch (ValidationException validationEx)
    {
        // 捕获手动验证抛出的异常
#if DEBUG
        void LogValidationErrors(Exception ex)
        {
            if (ex is ValidationException valEx)
            {
                if (valEx.ValidationResult != null)
                {
                    foreach (var memberName in valEx.ValidationResult.MemberNames)
                    {
                        Trace.TraceInformation("Class: {0}, Property: {1}, Error: {2}",
                            valEx.ValidationResult.MemberNames.Any() ? valEx.ValidationResult.MemberNames.First() : "Unknown",
                            memberName,
                            valEx.ValidationResult.ErrorMessage);
                    }
                }
                valEx.InnerException?.Let(LogValidationErrors);
            }
        }

        LogValidationErrors(validationEx);
#endif
        throw;
    }
    finally
    {
        // 恢复验证拦截器
        if (!validateSave && validationInterceptor != null)
        {
            DbContext.AddInterceptor(validationInterceptor);
        }
    }
}

关键修改说明

  1. 移除DbContext.Configuration依赖
    EF Core中无Configuration.ValidateOnSaveEnabled属性,改为临时移除ValidationBehavior拦截器实现跳过验证的效果,确保validateSave=false时与原EF6行为一致。

  2. 替换异常捕获逻辑
    EF Core不再抛出DbEntityValidationException,验证失败时会抛出DbUpdateException(内部嵌套ValidationException),或手动验证时直接抛出ValidationException。通过递归解析异常获取属性级的验证错误详情。

  3. 手动控制验证时机
    当validateSave=true时,调用DbContext.ValidateEntities()触发EF Core的实体验证,与原代码的验证逻辑对齐。

  4. 代码优化
    将重复的日志开关判断提取为变量,提升代码可读性与维护性。

额外注意事项

  • 若基于.NET Core/.NET 6+开发,建议使用依赖注入的IConfiguration替代ConfigurationManager.AppSettings,符合现代.NET规范。
  • 自定义Logger类的相关方法无需大幅修改,EF Core的EntityEntry与EF6的DbEntityEntry接口兼容。

内容的提问来源于stack exchange,提问作者Halil Kirişci

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 05:07:03