我有一个使用实体框架的项目。而在我的DbContext上调用SaveChanges时,我得到了以下异常:

System.Data.Entity.Validation.DbEntityValidationException:验证 一个或多个实体失败。参见'EntityValidationErrors'属性 欲知详情。

这一切都很好,但我不希望每次发生此异常时都附加调试器。此外,在生产环境中,我不能轻易地附加调试器,因此我必须竭尽全力重现这些错误。

我如何才能看到隐藏在DbEntityValidationException中的细节?


当前回答

要查看EntityValidationErrors集合,请将以下Watch表达式添加到Watch窗口。

((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors

我使用的是visual studio 2013

其他回答

在代码中使用try块

try
{
    // Your code...
    // 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;
}

你也可以在这里查看详细信息

http://mattrandle.me/viewing-entityvalidationerrors-in-visual-studio/ 一个或多个实体验证失败。更多细节请参见'EntityValidationErrors'属性 http://blogs.infosupport.com/improving-dbentityvalidationexception/

在调试过程中通过检查错误来快速找到有意义的错误消息:

添加一个快速手表: ((System.Data.Entity.Validation.DbEntityValidationException)例外)美元.EntityValidationErrors 向下钻取EntityValidationErrors,如下所示: > ValidationErrors >(收集项,如[0])> ErrorMessage

正如Martin所指出的,在DbEntityValidationResult中有更多信息。我发现在每条消息中同时获取POCO类名和属性名很有用,并且希望避免为此在所有[Required]标记上编写自定义ErrorMessage属性。

以下对Martin代码的调整为我解决了这些细节问题:

// Retrieve the error messages as a list of strings.
List<string> errorMessages = new List<string>();
foreach (DbEntityValidationResult validationResult in ex.EntityValidationErrors)
{
    string entityName = validationResult.Entry.Entity.GetType().Name;
    foreach (DbValidationError error in validationResult.ValidationErrors)
    {
        errorMessages.Add(entityName + "." + error.PropertyName + ": " + error.ErrorMessage);
    }
}

对于Azure函数,我们使用这个简单的扩展Microsoft.Extensions.Logging.ILogger

public static class LoggerExtensions
{
    public static void Error(this ILogger logger, string message, Exception exception)
    {
        if (exception is DbEntityValidationException dbException)
        {
            message += "\nValidation Errors: ";
            foreach (var error in dbException.EntityValidationErrors.SelectMany(entity => entity.ValidationErrors))
            {
                message += $"\n * Field name: {error.PropertyName}, Error message: {error.ErrorMessage}";
            }
        }

        logger.LogError(default(EventId), exception, message);
    }
}

以及示例用法:

try
{
    do something with request and EF
}
catch (Exception e)
{
    log.Error($"Failed to create customer due to an exception: {e.Message}", e);
    return await StringResponseUtil.CreateResponse(HttpStatusCode.InternalServerError, e.Message);
}

当您在catch{…打开“QuickWatch”窗口(ctrl+alt+q)并粘贴在那里:

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

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

对于Visual 2012+用户,他们只关心第一个错误,可能没有catch块,你甚至可以这样做:

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