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

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

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

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


person Naz    schedule 17.03.2011    source источник


Ответы (6)


Пока вы находитесь в режиме отладки в блоке 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
person GONeale    schedule 06.07.2011
comment
Если у вас нет блока catch, вы можете заменить ex на $exception и получить тот же результат. - person Ecyrb; 22.12.2011
comment
также убедитесь, что вы заменили ex на w/e ваш catch (Exception THIS) - person Eonasdan; 26.10.2012
comment
@Ecyrb, спасибо. вы сэкономили часы гугления. Кроме того, даже если число ошибок проверки равно 1, на самом деле в массиве есть два элемента с двумя ошибками. - person matrix; 20.08.2013
comment
Это не работает для меня (VS2015) ошибка CS0103: имя «$ exception» не существует в текущем контексте - person Tim Pohlmann; 14.03.2016
comment
@TimPohlmann Вы должны сделать это во время отладки. - person GONeale; 15.03.2016
comment
@GONeale Я пробовал это во время отладки - person Tim Pohlmann; 17.03.2016
comment
Для тех, кто не ссылается на System.Linq и использует непосредственное окно: System.Linq.Enumerable.ToList(System.Linq.Enumerable.ToList(((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors)[0].ValidationErrors)[0].ErrorMessage - person jpsimard-nyx; 24.03.2016

Вы могли бы попробовать это в блоке 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);
        }
    }
}
person Trent Scholl    schedule 23.03.2011

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

просто добавьте этот метод в основной класс 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() вашего контекста, и вы получите список, разделенный запятыми, содержащий все ошибки проверки объекта.

надеюсь, что это полезно.

person Chtiwi Malek    schedule 18.04.2015
comment
Создание строки с использованием этого string.Join() свойства ошибки и сообщений было полезно для использования в системе регистрации ошибок. - person Mark; 02.12.2020

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

public string Comment {get; set;}

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

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

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

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

person Wojciech Kotlinski    schedule 18.03.2011
comment
Ну, я спрашивал, как мне получить точное имя свойства, которое нарушает модель. Тем не менее, мне удалось преодолеть указанную вами проблему, используя [StringLength(Int32.MaxValue)] в качестве атрибута для моего свойства (как это было предложено Ладиславом Мрнкой, и я говорил об этом в этом вопросе stackoverflow.com/questions/5346155 /) Поводзения! знак равно - person Naz; 19.03.2011
comment
Это было брошено, когда я добавил новое свойство в свою модель в 4.1. Раньше в 4.1 работало отлично. Странный. Решается путем добавления аннотации ко всем свойствам в модели. - person Roberto Bonini; 22.03.2011

Я знаю, что это старый вопрос, но вот мой ответ:

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

Как видите, я полностью перевел свои сообщения об ошибках, включая имена свойств, чтобы затем использовать их в пользователе позже, например:

введите здесь описание изображения

person Sara NikitaUsefi    schedule 06.01.2020

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

person smirkingman    schedule 16.01.2015