从DbValidationException获取确切的错误类型


184

我遇到的情况是,我在EF 4.1的DatabaseInitializer()中初始化我的模型,并得到此烦人的错误,"Validation failed for one or more entities. See 'EntityValidationErrors' property for more details."所以,我转到EntityValidationErrors,有一个字段{System.Data.Entity.Validation.DbEntityValidationResult}完全无法提供有关它无法初始化的字段的信息。有没有办法获取有关此错误的更多信息?

要清除问题:

我知道如何解决字符串长度问题。我要问的是如何获取破坏模型的确切字段名称。

Answers:


377

catch {...}块中处于调试模式时,打开“ QuickWatch”窗口(ctrl+ alt+ q)并粘贴在其​​中:

((System.Data.Entity.Validation.DbEntityValidationException)ex).EntityValidationErrors

这将允许您深入到ValidationErrors树中。这是我发现的可以立即洞悉这些错误的最简单方法。

对于只关心第一个错误并且可能没有catch阻止的Visual 2012+用户,您甚至可以执行以下操作:

((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors.First().ValidationErrors.First().ErrorMessage

9
这比其他答案要好:)
Doug

98
如果没有catch块,则可以替换ex$exception并获得相同的结果。
Ecyrb,2011年

还要确保ex用w / e 取代您catch (Exception THIS)
身分

@Ecyrb,谢谢。您节省了数小时的谷歌搜索时间。同样,即使验证错误计数显示为1,实际上数组中的两个元素也存在两个错误。
矩阵

3
对于那些不引用System.Linq并使用即时窗口的用户:System.Linq.Enumerable.ToList(System.Linq.Enumerable.ToList(((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors)[0].ValidationErrors)[0].ErrorMessage
jpsimard-nyx

124

您可以在try / catch块中尝试吗?

catch (DbEntityValidationException dbEx)
{
    foreach (var validationErrors in dbEx.EntityValidationErrors)
    {
        foreach (var validationError in validationErrors.ValidationErrors)
        {
            Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
        }
    }
}

11

我认为最好的解决方案是集中处理此类错误。

只需将此方法添加到主DbContext类中:

public override int SaveChanges()
{
    try
    {
        return base.SaveChanges();
    }
    catch (DbEntityValidationException ex)
    {
        string errorMessages = string.Join("; ", ex.EntityValidationErrors.SelectMany(x => x.ValidationErrors).Select(x => x.PropertyName + ": " + x.ErrorMessage));
        throw new DbEntityValidationException(errorMessages);
    }
}

这将覆盖您上下文的 SaveChanges()方法,并且您将得到一个逗号分隔的列表,其中包含所有实体验证错误。

希望这会有所帮助。


4

好吧,我有同样的问题。我的模型在EF CTP5中运行良好,但是在尝试初始化它时却出现了错误““一个或多个实体验证失败”“,但无法在4.1中构建。我发现我拥有属性:

public string Comment {get; set;}

然后在覆盖初始化程序的种子方法中,我有相当长的注释(大约600个字母)。

我认为重点是:在EF 4.1 ,在某些情况下必须显式设置数据注释。对我来说,设置:

[StringLength(4000)] 
public string Comment {get; set;}

帮助了。由于CTP5对此没有任何问题,这很奇怪。


我问的是如何获取破坏模型的确切属性名称。但是,我设法克服了您使用[StringLength(Int32.MaxValue)]作为我的属性的属性所提出的问题(正如Ladislav Mrnka所建议的那样,我在此问题stackoverflow.com/questions/5346155/中对此进行了讨论。)Powodzenia!=)
纳兹

当我在4.1中向模型中添加新属性时,就会抛出该错误。在4.1之前可以完美工作。奇怪的。通过向模型中的所有属性添加注释来解决。
罗伯托·博尼尼

1

我发现创建SaveChanges包装器很有用,这使EntityValidationErrors更具可读性:

Public Sub SaveChanges(entities As Entities)

    Try
        entities.SaveChanges()

    Catch ex As DbEntityValidationException

        Dim msg As New StringBuilder
        msg.AppendLine(ex.Message)

        For Each vr As DbEntityValidationResult In ex.EntityValidationErrors
            For Each ve As DbValidationError In vr.ValidationErrors
                msg.AppendLine(String.Format("{0}: {1}", ve.PropertyName, ve.ErrorMessage))
            Next
        Next

        Throw New DbEntityValidationException(msg.ToString, ex.EntityValidationErrors, ex)

    End Try

End Sub

然后在整个项目中将“ entities.SaveChanges()”更改为“ SaveChanges(entities)”


0

我知道这是一个老问题,但这是我的答案:

catch (DbEntityValidationException ex)
   {
    String.Join("\n", ex.EntityValidationErrors
          .SelectMany(x => x.ValidationErrors)
          .Select(x => x.ErrorMessage)
          .ToArray());
   }

如果先使用代码,还可以使用多个资源文件来全球化错误消息

例如,我有这两个单独的资源文件,一个用于错误,一个用于属性名,我按如下方式使用它们: 在此处输入图片说明 在此处输入图片说明

public class Person 
    {
        [Required(ErrorMessageResourceName = "required",ErrorMessageResourceType =typeof(ErrorMessages))]
        [MaxLength(100,ErrorMessageResourceName = "maxLength", ErrorMessageResourceType = typeof(ErrorMessages))]
        [Display(Name = "FirstName",ResourceType = typeof(Properties))]
        public string FirstName { get; set; }
         }

如您所见,我已经完全翻译了错误消息,包括属性名称,因此以后可以在用户中使用它们,例如:

在此处输入图片说明

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.