Отримання точного типу помилки з DbValidationException


184

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

Щоб очистити речі:

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

Відповіді:


377

Поки ви перебуваєте в режимі налагодження в 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

9
Це краще, ніж інша відповідь :)
Doug

98
Якщо ви не маєте зловити блок, ви можете замінити exз $exceptionі отримати той же результат.
Ecyrb

також переконайтеся , що ви замінити exз ж / д ваш catch (Exception THIS)є
Eonasdan

@Ecyrb, спасибі ви зекономили години Google. Крім того, навіть якщо кількість помилок перевірки показано як 1, в масиві дійсно є два елементи з двома помилками.
матриця

3
Для тих, хто не посилається на System.Linq та використовує негайне вікно:System.Linq.Enumerable.ToList(System.Linq.Enumerable.ToList(((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors)[0].ValidationErrors)[0].ErrorMessage
jpsimard-nyx

124

Ви можете спробувати це у блоці спробу / лову?

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

11

Найкраще рішення, на мою думку, - це обробляти подібні помилки централізовано.

просто додайте цей метод до основного 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 не мав проблем з цим.


Ну, що я запитував, як я можу отримати точне ім'я властивості, яке порушує модель. Хоча мені вдалося подолати проблему, яку ви заявили, використовуючи [StringLength (Int32.MaxValue)] як атрибут для мого майна (як це запропонував Ладіслав Мрнка, і я говорив про це в цьому питанні stackoverflow.com/questions/5346155/… ) Породзенія! =)
Наз

Це було кинуто, коли я додав нову властивість до своєї моделі в 4.1. Раніше чудово працював у 4.1. Дивно. Вирішується додаванням анотації до всіх властивостей моделі.
Роберто Боніні

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

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


0

Я знаю, що це старе питання, але ось моя відповідь:

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

Як ви бачите, я повністю переклав свої повідомлення про помилки, включаючи імена властивостей, тому я можу потім використовувати їх у користувача, наприклад:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.