195

我有这样的情况,我在 EF 4.1 的 DatabaseInitializer() 中初始化我的模型并得到这个烦人的错误"Validation failed for one or more entities. See 'EntityValidationErrors' property for more details."所以,我转到这个 EntityValidationErrors 并且有一个字段{System.Data.Entity.Validation.DbEntityValidationResult}根本没有给我任何关于它无法初始化的字段的信息. 有没有办法获得有关此错误的更多信息?

清除事情:

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

4

7 回答 7

387

当您在块内处于调试模式时,catch {...}打开“QuickWatch”窗口(ctrl++ altq并粘贴到那里:

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

这将允许您深入到ValidationErrors树中。这是我发现即时了解这些错误的最简单方法。

对于只关心第一个错误并且可能没有catch阻塞的 Visual 2012+ 用户,您甚至可以这样做:

((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors.First().ValidationErrors.First().ErrorMessage
于 2011-07-06T08:19:12.320 回答
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);
        }
    }
}
于 2011-03-23T04:00:42.490 回答
14

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

只需将此方法添加到主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()方法,您将获得一个逗号分隔的列表,其中包含所有实体验证错误。

希望这会有所帮助。

于 2015-04-18T18:24:04.687 回答
4

好吧,我有同样的问题。我的模型在 EF CTP5 中运行良好,但未能在 4.1 中构建,当我尝试初始化它时出现相同的错误““一个或多个实体的验证失败”。我发现我有财产:

public string Comment {get; set;}

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

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

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

帮助。这很奇怪,因为 CTP5 对此没有任何问题。

于 2011-03-18T18:55:34.377 回答
2

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

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; }
         }

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

在此处输入图像描述

于 2020-01-06T15:40:05.257 回答
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)”

于 2015-01-16T13:00:37.183 回答
0

验证您尝试保存的所有不可为空的字段是否具有值。它实际上可能比找出神秘的错误消息花费的时间更少。

于 2021-08-07T01:17:44.873 回答