Den genauen Fehlertyp von DbValidationException eingeben

184

Ich habe die Situation, dass ich mein Modell in DatabaseInitializer () für EF 4.1 initialisiere und diesen nervigen Fehler "Validation failed for one or more entities. See 'EntityValidationErrors' property for more details."erhalte. Ich gehe also zu diesem EntityValidationErrors und es gibt ein Feld, {System.Data.Entity.Validation.DbEntityValidationResult}das mir überhaupt keine Informationen darüber gibt, welches Feld es nicht initialisieren konnte . Gibt es eine Möglichkeit, weitere Informationen zu diesem Fehler zu erhalten?

Um die Dinge zu klären:

Ich weiß, wie man das Problem mit der Stringlänge behebt. Ich frage, wie ich den genauen Feldnamen erhalte, der das Modell beschädigt.

Naz
quelle

Antworten:

377

Während Sie sich im Debug-Modus innerhalb des catch {...}Blocks befinden, öffnen Sie das Fenster "QuickWatch" ( ctrl+ alt+ q) und fügen Sie es dort ein:

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

Auf diese Weise können Sie einen Drilldown in den ValidationErrorsBaum durchführen. Dies ist der einfachste Weg, um sofort einen Einblick in diese Fehler zu erhalten.

Für Benutzer von Visual 2012+, die sich nur um den ersten Fehler kümmern und möglicherweise keinen catchBlock haben, können Sie sogar Folgendes tun:

((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors.First().ValidationErrors.First().ErrorMessage
GONeale
quelle
9
Dies ist besser als die andere Antwort :)
Doug
98
Wenn Sie nicht über einen catch - Block haben, können Sie ersetzen exmit $exceptionund das gleiche Ergebnis.
Ecyrb
excatch (Exception THIS)
Stellen
@Ecyrb, danke. Sie haben Stunden des Googelns gespart. Selbst wenn die Anzahl der Validierungsfehler als 1 angezeigt wird, enthält das Array tatsächlich zwei Elemente mit zwei Fehlern.
Matrix
3
Für diejenigen, die nicht auf System.Linq verweisen und das unmittelbare Fenster verwenden:System.Linq.Enumerable.ToList(System.Linq.Enumerable.ToList(((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors)[0].ValidationErrors)[0].ErrorMessage
jpsimard-nyx
124

Sie könnten dies in einem Try / Catch-Block versuchen?

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
quelle
11

Die beste Lösung ist meiner Meinung nach, diese Art von Fehlern zentral zu behandeln.

Fügen Sie diese Methode einfach der Hauptklasse hinzu 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);
    }
}

Dadurch wird die SaveChanges()Methode Ihres Kontexts überschrieben und Sie erhalten eine durch Kommas getrennte Liste mit allen Fehlern bei der Entitätsüberprüfung.

hoffe das ist hilfreich.

Chtiwi Malek
quelle
4

Nun, ich hatte das gleiche Problem. Mein Modell funktionierte in EF CTP5 gut, konnte jedoch 4.1 nicht mit demselben Fehler "" Validierung für eine oder mehrere Entitäten fehlgeschlagen "erstellen, als ich versuchte, es zu initialisieren. Ich stellte fest, dass ich Eigenschaft hatte:

public string Comment {get; set;}

Dann hatte ich bei der Seed-Methode im überschriebenen Initialisierer einen ziemlich langen Kommentar (ungefähr 600 Buchstaben).

Ich denke , der Punkt ist: in EF 4.1 Sie haben zu Einstelldaten Anmerkungen explizit in einigen Fällen. Für mich Einstellung:

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

geholfen. Es ist komisch, da CTP5 damit keine Probleme hatte.

Wojciech Kotlinski
quelle
Nun, ich habe gefragt, wie ich den genauen Eigenschaftsnamen erhalte, der das Modell beschädigt. Ich habe es jedoch geschafft, das von Ihnen angegebene Problem zu lösen, indem ich [StringLength (Int32.MaxValue)] als Attribut für meine Eigenschaft verwendet habe (wie es von Ladislav Mrnka vorgeschlagen wurde und ich in dieser Frage darüber gesprochen habe stackoverflow.com/questions/5346155/… ) Powodzenia! =)
Naz
Dies wurde ausgelöst, als ich meinem Modell in 4.1 eine neue Eigenschaft hinzufügte. Hat vorher in 4.1 perfekt funktioniert. Seltsam. Wird durch Hinzufügen von Anmerkungen zu allen Eigenschaften im Modell behoben.
Roberto Bonini
1

Ich fand es nützlich, einen SaveChanges-Wrapper zu erstellen, der die EntityValidationErrors besser lesbar macht:

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

und änderte dann 'entity.SaveChanges ()' in 'SaveChanges (entity)' in meinem gesamten Projekt

grinsender Mann
quelle
0

Ich weiß, dass es eine alte Frage ist, aber hier ist meine Antwort:

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

Wenn Sie zuerst Code verwenden, können Sie Ihre Fehlermeldungen auch mithilfe mehrerer Ressourcendateien globalisieren

Zum Beispiel habe ich diese zwei separaten Ressourcendateien, eine für Fehler und eine für Eigenschaftsnamen, und ich verwende sie wie folgt: Geben Sie hier die Bildbeschreibung ein Geben Sie hier die Bildbeschreibung ein

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

Wie Sie sehen, habe ich meine Fehlermeldungen einschließlich der Eigenschaftsnamen vollständig übersetzt, damit ich sie später im Benutzer verwenden kann, zum Beispiel:

Geben Sie hier die Bildbeschreibung ein

NikiUsefi
quelle