Получение точного типа ошибки из DbValidationException - PullRequest
182 голосов
/ 18 марта 2011

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

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

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

Ответы [ 5 ]

374 голосов
/ 06 июля 2011

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

Вы можете попробовать это в блоке 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);
        }
    }
}
10 голосов
/ 18 апреля 2015

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

просто добавьте этот метод в основной 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 голосов
/ 18 марта 2011

Ну, у меня была такая же проблема. Моя модель хорошо работала в EF CTP5, но не смогла встроить 4.1 с той же ошибкой "" Проверка не удалась для одной или нескольких сущностей ", когда я пытался ее инициализировать. Я выяснил, что у меня есть свойство:

public string Comment {get; set;}

Затем в методе seed в переопределенном инициализаторе у меня был довольно длинный (около 600 букв) комментарий.

Я думаю, суть в том, что в EF 4.1 у вас есть для явной установки аннотаций данных в некоторых случаях. Для меня настройка:

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

помогло. Это странно, поскольку у CTP5 с этим проблем не было.

1 голос
/ 16 января 2015

Мне показалось полезным создать оболочку 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 (entity)» во всем моем проекте

...