老实说,我不知道如何检查验证错误的内容。Visual Studio向我展示了这是一个包含8个对象的数组,因此出现8个验证错误。
实际上,如果在调试期间在Visual Studio中钻入该阵列,则应该看到错误。但是您也可以捕获异常,然后将错误写出到某些日志存储区或控制台中:
try{ // Your pre... // Could also be before try if you know the exception occurs in SaveChanges context.SaveChanges();}catch (DbEntityValidationException e){ foreach (var eve in e.EntityValidationErrors) { Console.WriteLine("Entity of type "{0}" in state "{1}" has the following validation errors:", eve.Entry.Entity.GetType().Name, eve.Entry.State); foreach (var ve in eve.ValidationErrors) { Console.WriteLine("- Property: "{0}", Error: "{1}"", ve.PropertyName, ve.ErrorMessage); } } throw;}EntityValidationErrors是表示无法成功验证的
ValidationErrors实体的集合,每个实体的内部集合是属性级别的错误列表。
这些验证消息通常足以找到问题的根源。
编辑
一些小改进:
违规属性的 值 可以包含在内循环中,如下所示:
foreach (var ve in eve.ValidationErrors) { Console.WriteLine("- Property: "{0}", Value: "{1}", Error: "{2}"", ve.PropertyName, eve.Entry.CurrentValues.GetValue<object>(ve.PropertyName), ve.ErrorMessage); }尽管调试
Debug.Write可能比
Console.WriteLine其更适用,因为它可以在所有类型的应用程序中使用,而不仅仅是控制台应用程序(感谢@Bart在下面的评论中提供他的注释)。
对于在生产中并且使用 Elmah
进行异常日志记录的Web应用程序,事实证明,这对于我创建自定义异常并进行覆盖
SaveChanges以抛出此新异常非常有用。
自定义异常类型如下所示:
public class FormattedDbEntityValidationException : Exception{ public FormattedDbEntityValidationException(DbEntityValidationException innerException) : base(null, innerException) { } public override string Message { get { var innerException = InnerException as DbEntityValidationException; if (innerException != null) { StringBuilder sb = new StringBuilder(); sb.AppendLine(); sb.AppendLine(); foreach (var eve in innerException.EntityValidationErrors) { sb.AppendLine(string.Format("- Entity of type "{0}" in state "{1}" has the following validation errors:", eve.Entry.Entity.GetType().FullName, eve.Entry.State)); foreach (var ve in eve.ValidationErrors) { sb.AppendLine(string.Format("-- Property: "{0}", Value: "{1}", Error: "{2}"", ve.PropertyName, eve.Entry.CurrentValues.GetValue<object>(ve.PropertyName), ve.ErrorMessage)); } } sb.AppendLine(); return sb.ToString(); } return base.Message; } }}并且
SaveChanges可以通过以下方式覆盖:
public class MyContext : DbContext{ // ... public override int SaveChanges() { try { return base.SaveChanges(); } catch (DbEntityValidationException e) { var newException = new FormattedDbEntityValidationException(e); throw newException; } }}几点评论:
Elmah在Web界面或已发送的电子邮件(如果已配置)中显示的黄色错误屏幕现在直接在消息顶部显示验证详细信息。
Message
在自定义异常中覆盖而不是覆盖属性ToString()
的好处是,标准ASP.NET“死亡黄屏(YSOD)”也显示此消息。与Elmah相反,YSOD显然不使用ToString()
,但是两者都显示Message
属性。将原始文件包装
DbEntityValidationException
为内部异常可确保原始堆栈跟踪仍然可用,并显示在Elmah和YSOD中。通过在行上设置一个断点,
throw newException;
您可以简单地将newException.Message
属性作为文本进行检查,而不必钻研验证集合,这有点尴尬,而且似乎并不适合所有人(请参见下面的评论)。



