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.

Naz
źródło

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
GONeale
źródło
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);
        }
    }
}
Trent Scholl
źródło
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.

Chtiwi Malek
źródło
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.

Wojciech Kotliński
źródło
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

uśmieszek
źródło
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

NikiUsefi
źródło