Ottenere l'errore esatto digitare da DbValidationException


184

Ho la situazione in cui sto inizializzando il mio modello in DatabaseInitializer () per EF 4.1 e ottengo questo fastidioso errore "Validation failed for one or more entities. See 'EntityValidationErrors' property for more details."Quindi, vado a questo EntityValidationErrors e c'è un campo {System.Data.Entity.Validation.DbEntityValidationResult}che non mi dà alcuna informazione su quale campo non è stato in grado di inizializzare . C'è un modo per ottenere maggiori informazioni su questo errore?

Per chiarire le cose:

So come risolvere il problema della lunghezza della stringa. Quello che sto chiedendo è come posso ottenere il nome del campo esatto che sta rompendo il modello.

Risposte:


377

Mentre sei in modalità debug all'interno del catch {...}blocco, apri la finestra "QuickWatch" ( ctrl+ alt+ q) e incolla lì:

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

Ciò ti consentirà di eseguire il drill down ValidationErrorssull'albero. È il modo più semplice che ho trovato per ottenere una visione istantanea di questi errori.

Per gli utenti di Visual 2012+ che si preoccupano solo del primo errore e potrebbero non avere un catchblocco, puoi persino fare:

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

9
È meglio dell'altra risposta :)
Doug,

98
Se non si dispone di un blocco catch, è possibile sostituire excon $exceptione ottenere lo stesso risultato.
Ecyrb,

assicurati anche di sostituire excon w / e your catch (Exception THIS)is
Eonasdan,

@Ecyrb, grazie. hai risparmiato ore su Google. Inoltre, anche se il conteggio degli errori di convalida viene visualizzato come 1, in realtà ci sono due elementi nella matrice con due errori.
matrice

3
Per coloro che non fanno riferimento a System.Linq e utilizzano la finestra immediata:System.Linq.Enumerable.ToList(System.Linq.Enumerable.ToList(((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors)[0].ValidationErrors)[0].ErrorMessage
jpsimard-nyx

124

Potresti provare questo in un blocco 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

La migliore soluzione secondo me è quella di gestire questo tipo di errori in modo centralizzato.

aggiungi questo metodo alla DbContextclasse principale :

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

Questo sovrascriverà il SaveChanges()metodo del tuo contesto e otterrai un elenco separato da virgole contenente tutti gli errori di convalida dell'entità.

spero che sia utile


4

Bene, ho avuto lo stesso problema. Il mio modello ha funzionato bene in EF CTP5 ma non è riuscito a compilare in 4.1 con lo stesso errore "" Convalida non riuscita per una o più entità "quando ho provato a inizializzarlo. Ho capito che avevo proprietà:

public string Comment {get; set;}

Quindi nel metodo seed nell'inizializzatore annullato, ho avuto un commento piuttosto lungo (circa 600 lettere).

Credo che il punto è: in EF 4.1 si deve per le annotazioni di dati impostare in modo esplicito in alcuni casi. Per me, l'impostazione:

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

aiutato. È strano dal momento che CTP5 non ha avuto problemi con questo.


Bene, quello che stavo chiedendo è come ottenere il nome esatto della proprietà che rompe il modello. Tuttavia, sono riuscito a superare il problema che hai dichiarato usando [StringLength (Int32.MaxValue)] come attributo per la mia proprietà (come suggerito da Ladislav Mrnka e ne ho parlato in questa domanda stackoverflow.com/questions/5346155/… ) Powodzenia! =)
Naz,

Questo è stato lanciato quando ho aggiunto una nuova proprietà al mio modello in 4.1. In precedenza funzionava perfettamente in 4.1. Strano. Risolto aggiungendo l'annotazione a tutte le proprietà nel modello.
Roberto Bonini,

1

Ho trovato utile creare un wrapper SaveChanges che renda più leggibili 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

e poi cambiato 'entity.SaveChanges ()' in 'SaveChanges (entity)' in tutto il mio progetto


0

So che è una vecchia domanda ma ecco la mia risposta:

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

e se si utilizza prima il codice, è anche possibile globalizzare i messaggi di errore utilizzando più file di risorse

Ad esempio, ho questi due file di risorse separati, uno per errore e uno per nome proprietà e li uso come segue: inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine

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

Come puoi vedere, ho tradotto completamente i miei messaggi di errore, inclusi i nomi delle proprietà, in modo da poterli utilizzare in seguito in seguito, ad esempio:

inserisci qui la descrizione dell'immagine

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.