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); } } }
关键修改说明
移除
DbContext.Configuration依赖
EF Core中无Configuration.ValidateOnSaveEnabled属性,改为临时移除ValidationBehavior拦截器实现跳过验证的效果,确保validateSave=false时与原EF6行为一致。替换异常捕获逻辑
EF Core不再抛出DbEntityValidationException,验证失败时会抛出DbUpdateException(内部嵌套ValidationException),或手动验证时直接抛出ValidationException。通过递归解析异常获取属性级的验证错误详情。手动控制验证时机
当validateSave=true时,调用DbContext.ValidateEntities()触发EF Core的实体验证,与原代码的验证逻辑对齐。代码优化
将重复的日志开关判断提取为变量,提升代码可读性与维护性。
额外注意事项
- 若基于.NET Core/.NET 6+开发,建议使用依赖注入的
IConfiguration替代ConfigurationManager.AppSettings,符合现代.NET规范。 - 自定义
Logger类的相关方法无需大幅修改,EF Core的EntityEntry与EF6的DbEntityEntry接口兼容。
内容的提问来源于stack exchange,提问作者Halil Kirişci
相关产品推荐
相关产品推荐

