Uzyskiwanie dokładnego błędu wpisz z DbValidationException


184

Mam sytuację, w której inicjuję mój model w DatabaseInitializer () dla EF 4.1 i otrzymuję ten irytujący błąd. "Validation failed for one or more entities. See 'EntityValidationErrors' property for more details."Więc przechodzę do tego EntityValidationErrors i jest pole, {System.Data.Entity.Validation.DbEntityValidationResult}które nie daje mi żadnych informacji o tym, które pole nie było w stanie zainicjować . Czy istnieje sposób, aby uzyskać więcej informacji o tym błędzie?

Aby usunąć rzeczy:

Wiem, jak rozwiązać problem długości łańcucha. Pytam o to, jak uzyskać dokładną nazwę pola, która psuje model.

Odpowiedzi:


377

W trybie debugowania w catch {...}bloku otwórz okno „QuickWatch” ( ctrl+ alt+ q) i wklej tam:

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

To pozwoli ci zejść do ValidationErrorsdrzewa. To najłatwiejszy sposób, w jaki udało mi się uzyskać natychmiastowy wgląd w te błędy.

Dla użytkowników Visual 2012+, którym zależy tylko na pierwszym błędzie i którzy mogą nie mieć catchbloku, możesz nawet:

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

9
To lepsze niż inna odpowiedź :)
Doug

98
Jeśli nie masz bloku catch można zastąpić exz $exceptioni uzyskać ten sam rezultat.
Ecyrb

upewnij się także, że zamienisz na exw / e your catch (Exception THIS)is
Eonasdan,

@Ecyrb, dzięki. zaoszczędziłeś godziny Googlingu. Ponadto, nawet jeśli liczba błędów sprawdzania poprawności jest pokazana jako 1, w rzeczywistości są dwa elementy w tablicy z dwoma błędami.
matryca

3
Dla tych, którzy nie odwołują się do System.Linq i używają bezpośredniego okna:System.Linq.Enumerable.ToList(System.Linq.Enumerable.ToList(((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors)[0].ValidationErrors)[0].ErrorMessage
jpsimard-nyx

124

Możesz spróbować tego w bloku 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);
        }
    }
}

11

Moim zdaniem najlepszym rozwiązaniem jest radzenie sobie z tego rodzaju błędami w sposób scentralizowany.

po prostu dodaj tę metodę do głównej DbContextklasy:

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

Spowoduje to zastąpienie SaveChanges()metody kontekstu, a otrzymasz listę oddzieloną przecinkami zawierającą wszystkie błędy sprawdzania poprawności encji.

mam nadzieję, że to jest pomocne.


4

Miałem ten sam problem. Mój model działał dobrze w EF CTP5, ale nie udało się go zbudować w wersji 4.1 z tym samym błędem „„ Sprawdzanie poprawności nie powiodło się dla jednej lub więcej jednostek ”, gdy próbowałem go zainicjować. Stwierdziłem, że mam właściwość

public string Comment {get; set;}

Następnie w metodzie seed w przesłoniętym inicjalizatorze miałem dość długi komentarz (około 600 liter).

Myślę, że chodzi o to: w EF 4.1 Państwo mieć do adnotacji zestaw danych bezpośrednio w niektórych przypadkach. Dla mnie ustawienie:

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

pomógł. To dziwne, ponieważ CTP5 nie miał z tym problemów.


O co pytałem, jak uzyskać dokładną nazwę właściwości, która psuje model. Mimo to udało mi się rozwiązać problem, który podałeś, używając [StringLength (Int32.MaxValue)] jako atrybutu mojej właściwości (jak sugerował Ladislav Mrnka i rozmawiałem o tym w tym pytaniu stackoverflow.com/questions/5346155/... ) Powodzenia! =)
Naz

Zostało to rzucone, gdy dodałem nową właściwość do mojego modelu w 4.1. Wcześniej działał doskonale w wersji 4.1. Dziwne. Rozwiązany przez dodanie adnotacji do wszystkich właściwości w modelu.
Roberto Bonini

1

Uważam, że przydatne jest utworzenie opakowania SaveChanges, które sprawia, że ​​EntityValidationErrors jest bardziej czytelny:

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

a następnie zmieniłem „podmioty.SaveChanges ()” na „SaveChanges (podmioty)” w całym moim projekcie


0

Wiem, że to stare pytanie, ale oto moja odpowiedź:

catch (DbEntityValidationException ex)
   {
    String.Join("\n", ex.EntityValidationErrors
          .SelectMany(x => x.ValidationErrors)
          .Select(x => x.ErrorMessage)
          .ToArray());
   }

a jeśli najpierw użyjesz kodu, możesz także zglobalizować komunikaty o błędach, używając wielu plików zasobów

Na przykład mam te dwa osobne pliki zasobów, jeden dla błędu, a drugi dla nazwy właściwości i używam ich w następujący sposób: wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj

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

Jak widać, całkowicie przetłumaczyłem komunikaty o błędach, w tym nazwy właściwości, dzięki czemu mogłem je później wykorzystać na przykład u użytkownika:

wprowadź opis zdjęcia tutaj

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.