Получение точного типа ошибки из DbValidationException

У меня есть ситуация, когда я инициализирую мою модель в DatabaseInitializer() для EF 4.1 и получаю эту досадную ошибку "Validation failed for one or more entities. See 'EntityValidationErrors' property for more details." Итак, я перехожу к этому EntityValidationErrors и есть поле {System.Data.Entity.Validation.DbEntityValidationResult}, которое не дает мне никакой информации на все о том, в каком поле он не смог инициализировать. Есть ли способ получить дополнительную информацию об этой ошибке?

Чтобы прояснить ситуацию:

Я знаю, как исправить проблему длины строки. Я спрашиваю, как получить точное имя поля, которое нарушает модель.

Ответ 1

Пока вы находитесь в режиме отладки в блоке 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

Ответ 2

Вы можете попробовать это в блоке 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);
        }
    }
}

Ответ 3

Лучшим решением, на мой взгляд, является централизованное обращение с такими ошибками.

просто добавьте этот метод в основной класс 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 не было проблем с этим.

Ответ 5

Мне было полезно создать оболочку 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

а затем изменил "entity.SaveChanges()" на "SaveChanges (сущности)" во всем моем проекте