Convalida non riuscita per una o più entità. Vedi la proprietà 'EntityValidationErrors' per maggiori dettagli


804

Sto riscontrando questo errore durante il seeding del mio database con il primo approccio al codice.

Convalida non riuscita per una o più entità. Vedi la proprietà 'EntityValidationErrors' per maggiori dettagli.

Ad essere sincero, non so come controllare il contenuto degli errori di convalida. Visual Studio mi mostra che è un array con 8 oggetti, quindi 8 errori di validazione.

Funzionava con il mio modello precedente, ma ho apportato alcune modifiche che spiego di seguito:

  • Ho avuto un enum chiamato Status, l'ho cambiato in una classe chiamata Status
  • Ho cambiato la classe ApplicantsPositionHistory per avere 2 chiavi esterne nella stessa tabella

Mi scusi per il codice lungo, ma devo incollarlo tutto. L'eccezione viene generata nell'ultima riga del seguente codice.

namespace Data.Model
{  
    public class Position
    {
        [DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.Identity)]   
        public int PositionID { get; set; }

        [Required(ErrorMessage = "Position name is required.")]
        [StringLength(20, MinimumLength = 3, ErrorMessage = "Name should not be longer than 20 characters.")]
        [Display(Name = "Position name")]              
        public string name { get; set; }

        [Required(ErrorMessage = "Number of years is required")] 
        [Display(Name = "Number of years")]        
        public int yearsExperienceRequired { get; set; }

        public virtual ICollection<ApplicantPosition> applicantPosition { get; set; }
    }

    public class Applicant
    {
        [DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.Identity)]      
        public int ApplicantID { get; set; }

        [Required(ErrorMessage = "Name is required")] 
        [StringLength(20, MinimumLength = 3, ErrorMessage="Name should not be longer than 20 characters.")]
        [Display(Name = "First and LastName")]
        public string name { get; set; }

        [Required(ErrorMessage = "Telephone number is required")] 
        [StringLength(10, MinimumLength = 3, ErrorMessage = "Telephone should not be longer than 20 characters.")]
        [Display(Name = "Telephone Number")]
        public string telephone { get; set; }

        [Required(ErrorMessage = "Skype username is required")] 
        [StringLength(10, MinimumLength = 3, ErrorMessage = "Skype user should not be longer than 20 characters.")]
        [Display(Name = "Skype Username")]
        public string skypeuser { get; set; }

        public byte[] photo { get; set; }

        public virtual ICollection<ApplicantPosition> applicantPosition { get; set; }
    }

    public class ApplicantPosition
    {
        [Key]
        [Column("ApplicantID", Order = 0)]
        public int ApplicantID { get; set; }

        [Key]
        [Column("PositionID", Order = 1)]
        public int PositionID { get; set; }

        public virtual Position Position { get; set; }

        public virtual Applicant Applicant { get; set; }

        [Required(ErrorMessage = "Applied date is required")] 
        [DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
        [Display(Name = "Date applied")]     
        public DateTime appliedDate { get; set; }

        [Column("StatusID", Order = 0)]
        public int StatusID { get; set; }

        public Status CurrentStatus { get; set; }

        //[NotMapped]
        //public int numberOfApplicantsApplied
        //{
        //    get
        //    {
        //        int query =
        //             (from ap in Position
        //              where ap.Status == (int)Status.Applied
        //              select ap
        //                  ).Count();
        //        return query;
        //    }
        //}
    }

    public class Address
    {
        [StringLength(20, MinimumLength = 3, ErrorMessage = "Country should not be longer than 20 characters.")]
        public string Country { get; set; }

        [StringLength(20, MinimumLength = 3, ErrorMessage = "City  should not be longer than 20 characters.")]
        public string City { get; set; }

        [StringLength(50, MinimumLength = 3, ErrorMessage = "Address  should not be longer than 50 characters.")]
        [Display(Name = "Address Line 1")]     
        public string AddressLine1 { get; set; }

        [Display(Name = "Address Line 2")]
        public string AddressLine2 { get; set; }   
    }

    public class ApplicationPositionHistory
    {
        [DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.Identity)]
        public int ApplicationPositionHistoryID { get; set; }

        public ApplicantPosition applicantPosition { get; set; }

        [Column("oldStatusID")]
        public int oldStatusID { get; set; }

        [Column("newStatusID")]
        public int newStatusID { get; set; }

        public Status oldStatus { get; set; }

        public Status newStatus { get; set; }

        [StringLength(500, MinimumLength = 3, ErrorMessage = "Comments  should not be longer than 500 characters.")]
        [Display(Name = "Comments")]
        public string comments { get; set; }

        [DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
        [Display(Name = "Date")]     
        public DateTime dateModified { get; set; }
    }

    public class Status
    {
        [DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.Identity)]
        public int StatusID { get; set; }

        [StringLength(20, MinimumLength = 3, ErrorMessage = "Status  should not be longer than 20 characters.")]
        [Display(Name = "Status")]
        public string status { get; set; }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using System.IO;

namespace Data.Model
{
    public class HRContextInitializer : DropCreateDatabaseAlways<HRContext>
    {
        protected override void Seed(HRContext context)
        {
            #region Status
            Status applied = new Status() { status = "Applied" };
            Status reviewedByHR = new Status() { status = "Reviewed By HR" };
            Status approvedByHR = new Status() { status = "Approved by HR" };
            Status rejectedByHR = new Status() { status = "Rejected by HR" };
            Status assignedToTechnicalDepartment = new Status() { status = "Assigned to Technical Department" };
            Status approvedByTechnicalDepartment = new Status() { status = "Approved by Technical Department" };
            Status rejectedByTechnicalDepartment = new Status() { status = "Rejected by Technical Department" };

            Status assignedToGeneralManager = new Status() { status = "Assigned to General Manager" };
            Status approvedByGeneralManager = new Status() { status = "Approved by General Manager" };
            Status rejectedByGeneralManager = new Status() { status = "Rejected by General Manager" };

            context.Status.Add(applied);
            context.Status.Add(reviewedByHR);
            context.Status.Add(approvedByHR);
            context.Status.Add(rejectedByHR);
            context.Status.Add(assignedToTechnicalDepartment);
            context.Status.Add(approvedByTechnicalDepartment);
            context.Status.Add(rejectedByTechnicalDepartment);
            context.Status.Add(assignedToGeneralManager);
            context.Status.Add(approvedByGeneralManager);
            context.Status.Add(rejectedByGeneralManager); 
            #endregion    

            #region Position
            Position netdeveloper = new Position() { name = ".net developer", yearsExperienceRequired = 5 };
            Position javadeveloper = new Position() { name = "java developer", yearsExperienceRequired = 5 };
            context.Positions.Add(netdeveloper);
            context.Positions.Add(javadeveloper); 
            #endregion

            #region Applicants
            Applicant luis = new Applicant()
            {
                name = "Luis",
                skypeuser = "le.valencia",
                telephone = "0491732825",
                photo = File.ReadAllBytes(@"C:\Users\LUIS.SIMBIOS\Documents\Visual Studio 2010\Projects\SlnHR\HRRazorForms\Content\pictures\1.jpg")
            };

            Applicant john = new Applicant()
            {
                name = "John",
                skypeuser = "jo.valencia",
                telephone = "3435343543",
                photo = File.ReadAllBytes(@"C:\Users\LUIS.SIMBIOS\Documents\Visual Studio 2010\Projects\SlnHR\HRRazorForms\Content\pictures\2.jpg")
            };

            context.Applicants.Add(luis);
            context.Applicants.Add(john); 
            #endregion

            #region ApplicantsPositions
            ApplicantPosition appicantposition = new ApplicantPosition()
            {
                Applicant = luis,
                Position = netdeveloper,
                appliedDate = DateTime.Today,
                StatusID = 1
            };

            ApplicantPosition appicantposition2 = new ApplicantPosition()
            {
                Applicant = john,
                Position = javadeveloper,
                appliedDate = DateTime.Today,
                StatusID = 1
            };        

            context.ApplicantsPositions.Add(appicantposition);            
            context.ApplicantsPositions.Add(appicantposition2); 
            #endregion

            context.SaveChanges(); --->> Error here
        }
    }
}

Risposte:


1237

Ad essere sincero, non so come controllare il contenuto degli errori di convalida. Visual Studio mi mostra che è un array con 8 oggetti, quindi 8 errori di validazione.

In realtà dovresti vedere gli errori se esegui il drill in quell'array in Visual Studio durante il debug. Ma puoi anche catturare l'eccezione e quindi scrivere gli errori in qualche archivio di registrazione o console:

try
{
    // Your code...
    // Could also be before try if you know the exception occurs in SaveChanges

    context.SaveChanges();
}
catch (DbEntityValidationException e)
{
    foreach (var eve in e.EntityValidationErrors)
    {
        Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
            eve.Entry.Entity.GetType().Name, eve.Entry.State);
        foreach (var ve in eve.ValidationErrors)
        {
            Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
                ve.PropertyName, ve.ErrorMessage);
        }
    }
    throw;
}

EntityValidationErrors è una raccolta che rappresenta le entità che non possono essere validate con successo e la raccolta interna ValidationErrors per entità è un elenco di errori a livello di proprietà.

Questi messaggi di convalida sono in genere abbastanza utili per trovare l'origine del problema.

modificare

Alcuni lievi miglioramenti:

Il valore della proprietà offensiva può essere incluso nel ciclo interno in questo modo:

        foreach (var ve in eve.ValidationErrors)
        {
            Console.WriteLine("- Property: \"{0}\", Value: \"{1}\", Error: \"{2}\"",
                ve.PropertyName,
                eve.Entry.CurrentValues.GetValue<object>(ve.PropertyName),
                ve.ErrorMessage);
        }

Mentre il debug Debug.Writepotrebbe essere preferibile rispetto a Console.WriteLinecome funziona in tutti i tipi di applicazioni, non solo le applicazioni console (grazie a @Bart per la sua nota nei commenti qui sotto).

Per le applicazioni Web in produzione e che utilizzano Elmah per la registrazione delle eccezioni, mi è stato molto utile creare un'eccezione personalizzata e sovrascriverla SaveChangesper lanciare questa nuova eccezione.

Il tipo di eccezione personalizzato è simile al seguente:

public class FormattedDbEntityValidationException : Exception
{
    public FormattedDbEntityValidationException(DbEntityValidationException innerException) :
        base(null, innerException)
    {
    }

    public override string Message
    {
        get
        {
            var innerException = InnerException as DbEntityValidationException;
            if (innerException != null)
            {
                StringBuilder sb = new StringBuilder();

                sb.AppendLine();
                sb.AppendLine();
                foreach (var eve in innerException.EntityValidationErrors)
                {
                    sb.AppendLine(string.Format("- Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
                        eve.Entry.Entity.GetType().FullName, eve.Entry.State));
                    foreach (var ve in eve.ValidationErrors)
                    {
                        sb.AppendLine(string.Format("-- Property: \"{0}\", Value: \"{1}\", Error: \"{2}\"",
                            ve.PropertyName,
                            eve.Entry.CurrentValues.GetValue<object>(ve.PropertyName),
                            ve.ErrorMessage));
                    }
                }
                sb.AppendLine();

                return sb.ToString();
            }

            return base.Message;
        }
    }
}

E SaveChangespuò essere sovrascritto nel modo seguente:

public class MyContext : DbContext
{
    // ...

    public override int SaveChanges()
    {
        try
        {
            return base.SaveChanges();
        }
        catch (DbEntityValidationException e)
        {
            var newException = new FormattedDbEntityValidationException(e);
            throw newException;
        }
    }
}

Alcune osservazioni:

  • La schermata di errore gialla che Elmah mostra nell'interfaccia web o nelle e-mail inviate (se lo hai configurato) ora mostra i dettagli di convalida direttamente nella parte superiore del messaggio.

  • Sovrascrivere la Messageproprietà nell'eccezione personalizzata anziché sovrascrivere ToString()ha il vantaggio che lo standard ASP.NET "Yellow screen of death (YSOD)" visualizza anche questo messaggio. Contrariamente a Elmah, YSOD apparentemente non usa ToString(), ma entrambi mostrano la Messageproprietà.

  • Il confezionamento dell'originale DbEntityValidationExceptioncome eccezione interna garantisce che la traccia dello stack originale sia ancora disponibile e venga visualizzata in Elmah e YSOD.

  • Impostando un punto di interruzione sulla linea, throw newException;è possibile semplicemente ispezionare la newException.Messageproprietà come testo anziché eseguire il drill sulle raccolte di convalida, il che è un po 'scomodo e non sembra funzionare facilmente per tutti (vedere i commenti di seguito).


87
Il drill in l'eccezione non fa nulla. Dice solo che esiste un DbEntityValidationResult ma non ti consente di espandere !!
Shumii,

30
@Shumii Vedi questa risposta per espandere l'eccezione.
Cavyn VonDeylen,

18
Solo per estendere una soluzione elegante. È possibile che si desideri sovrascrivere il metodo savechanges nella propria classe DbContext, quindi aggiungere il blocco catch, in cui il blocco try prova a salvare (base.SaveChanges ()) e il blocco catch cattura solo DbEntityValidationException. In questo modo, non è necessario aggiungerlo in ogni posizione in cui si salvano le modifiche.
Milton,

7
Questo mi ha salvato la pancetta in più di un'occasione. Ho potuto votare una sola volta. Avrei voluto che mi facessero votare per ogni volta che l'ho copiato e incollato.
Damon Drake,

5
+2 per il codice. Davvero un salvatore :) -1 per l'uso Console.WriteLine, stimo che più persone stiano scrivendo progetti web che console per app al giorno d'oggi, e Debug.Writefunziona in entrambi ...
Bart,

459

Puoi farlo da Visual Studio durante il debug senza scrivere alcun codice, nemmeno un blocco catch.

Aggiungi un orologio con il nome:

((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors

L'espressione da guardare $exception mostra qualsiasi eccezione generata nel contesto corrente, anche se non è stata rilevata e assegnata a una variabile.

Basato su http://mattrandle.me/viewing-entityvalidationerrors-in-visual-studio/


39
+1 Soluzione decisamente migliore e non richiede modifiche al codice. Fantastico
Justas,

4
+1 questo è molto, molto utile! Non è nemmeno necessario disporre di un blocco try / catch. Basta incollarlo nella watch list quando VS si rompe e voilà .. hai davanti a te gli errori di validazione.
theyetiman,

40
un paio di volte all'anno dimentico come fare e trovo questa risposta
Justin Moore,

3
@zairja Non l'ho testato in vb.net, ma sembra che la variabile sia definita anche per vb.net in msdn.microsoft.com/en-us/library/ms164891.aspx , ma probabilmente il cast non è definito per vb.net, e invece dovresti probabilmente fare DirectCast ($ exception, System.Data.Entity.Validation.DbEntityValidationException)
vedi il

2
So che "grazie" non sono i benvenuti nei commenti ma per il gusto di impedirmi ore di tempo sprecato ... grazie!
Lutero,

105

Questo potrebbe effettivamente farlo senza dover scrivere codice:

Nel tuo blocco catch, aggiungi un punto di interruzione nella seguente riga di codice:

catch (Exception exception)
{

}

Ora se si exceptionpassa con il mouse o lo si aggiunge a Watche quindi si naviga nei dettagli dell'eccezione come mostrato di seguito; vedrai quali particolari colonne causano / stanno causando il problema poiché questo errore si verifica in genere quando viene violato un vincolo di tabella.

inserisci qui la descrizione dell'immagine

Grande immagine


4
Questo approccio è molto semplice e sfrutta l'IDE :)
dsnunez,

3
Questa è una buona soluzione perché è veloce, semplice, utilizza l'IDE e mi ha fatto risparmiare un sacco di tempo.
maxshuty

2
Mi piace in questo modo "Come essere un programmatore e non fare il codice"
aperto e gratuito

1
Grazie. Questo è semplice ma è fantastico visualizzare l'eccezione utilizzando IDE.
Thomas.Benz,

soluzione perfetta
Neeraj Singh Chouhan,

46

Ecco come è possibile controllare il contenuto di EntityValidationErrors in Visual Studio (senza scrivere codice aggiuntivo) vale a dire durante il debug in IDE .

Il problema?

Hai ragione, Visualizza i dettagli del debugger di Visual Studio non mostra gli errori effettivi all'interno della EntityValidationErrorsraccolta.

inserisci qui la descrizione dell'immagine

La soluzione!

Aggiungi la seguente espressione in una finestra di Quick Watch e fai clic su Rivaluta .

((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors

Nel mio caso, vedi come sono in grado di espandermi ValidationErrors Listall'interno della EntityValidationErrorscollezione

inserisci qui la descrizione dell'immagine

Riferimenti: post sul blog mattrandle.me , la risposta di @ yoel


3
perché questo non è stato risolto? dovrebbe mostrare l'errore non qualcos'altro
Geomorillo

2
L'errore di convalida mostra l'errore di proprietà, ad es. campo obbligatorio, buona risposta, grazie
hamzeh.hanandeh,

1
Grande! Mi ha salvato la notte! :)
Patrick,

1
questo è un modo intelligente per visualizzare l'errore esatto nell'orologio ... grazie!
Qwerty,

39

Per un modo rapido per vedere il primo errore senza nemmeno aggiungere un orologio, puoi incollarlo nella finestra immediata:

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

1
Puoi anche usare $ exception.EntityValidationErrors.SelectMany (x => x.ValidationErrors) .Seleziona (x => x.ErrorMessage) per ottenerli tutti :) imho usando la finestra immediata è la risposta migliore
chrispepper1989

15

Per chiunque lavori VB.NET

Try
Catch ex As DbEntityValidationException
    For Each a In ex.EntityValidationErrors
        For Each b In a.ValidationErrors
            Dim st1 As String = b.PropertyName
            Dim st2 As String = b.ErrorMessage
        Next
    Next
End Try

12

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

o:

((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors

Se non ci si trova in try / catch o non si ha accesso all'oggetto eccezione.

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.


10

Se stai semplicemente rilevando un'eccezione generica, potrebbe essere utile lanciarla come DbEntityValidationException . Questo tipo di eccezione ha una proprietà Errori di convalida e continuando ad espandervi, troverete tutti i problemi.

Ad esempio, se si inserisce un punto di interruzione nella cattura, è possibile gettare un orologio in un orologio:

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

Un esempio di errore è se un campo non consente valori null e hai una stringa null, vedrai che il campo è obbligatorio.


9

basta controllare la lunghezza del campo della tabella del database. Il testo di input è maggiore della lunghezza del tipo di dati del campo colonna


9

Nel debug, è possibile inserire questo nel campo di immissione del valutatore espressioni QuickWatch:

context.GetValidationErrors()

8

La risposta di @Slauma è davvero eccezionale, ma ho scoperto che non funzionava quando una proprietà ComplexType non era valida.

Ad esempio, supponiamo di avere una proprietà Phonedel tipo complesso PhoneNumber. Se la AreaCodeproprietà non è valida, il nome della proprietà ve.PropertyNamesè "Phone.AreaCode". Ciò causa il eve.Entry.CurrentValues<object>(ve.PropertyName)fallimento della chiamata .

Per risolvere questo problema, puoi dividere il nome della proprietà in ciascuno ., quindi ricorrere attraverso l'array risultante dei nomi delle proprietà. Alla fine, quando arrivi in ​​fondo alla catena, puoi semplicemente restituire il valore della proprietà.

Di seguito è la FormattedDbEntityValidationExceptionclasse di @ Slauma con supporto per ComplexTypes.

Godere!

[Serializable]
public class FormattedDbEntityValidationException : Exception
{
    public FormattedDbEntityValidationException(DbEntityValidationException innerException) :
        base(null, innerException)
    {
    }

    public override string Message
    {
        get
        {
            var innerException = InnerException as DbEntityValidationException;
            if (innerException == null) return base.Message;

            var sb = new StringBuilder();

            sb.AppendLine();
            sb.AppendLine();
            foreach (var eve in innerException.EntityValidationErrors)
            {
                sb.AppendLine(string.Format("- Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
                    eve.Entry.Entity.GetType().FullName, eve.Entry.State));
                foreach (var ve in eve.ValidationErrors)
                {
                    object value;
                    if (ve.PropertyName.Contains("."))
                    {
                        var propertyChain = ve.PropertyName.Split('.');
                        var complexProperty = eve.Entry.CurrentValues.GetValue<DbPropertyValues>(propertyChain.First());
                        value = GetComplexPropertyValue(complexProperty, propertyChain.Skip(1).ToArray());
                    }
                    else
                    {
                        value = eve.Entry.CurrentValues.GetValue<object>(ve.PropertyName);
                    }
                    sb.AppendLine(string.Format("-- Property: \"{0}\", Value: \"{1}\", Error: \"{2}\"",
                        ve.PropertyName,
                        value,
                        ve.ErrorMessage));
                }
            }
            sb.AppendLine();

            return sb.ToString();
        }
    }

    private static object GetComplexPropertyValue(DbPropertyValues propertyValues, string[] propertyChain)
    {
        var propertyName = propertyChain.First();
        return propertyChain.Count() == 1 
            ? propertyValues[propertyName] 
            : GetComplexPropertyValue((DbPropertyValues)propertyValues[propertyName], propertyChain.Skip(1).ToArray());
    }
}

1
Non posso credere che più persone non abbiano votato a favore di questo, in quanto è uno scenario molto reale e mi ha fatto impazzire nelle ultime due notti. Sai quella sensazione che provi quando ti rendi conto della gestione degli errori è ciò che sta effettivamente generando l'errore? Ugh.
DJ Grossman,

7

Si noti che Entity.GetType().BaseType.Namefornisce il nome del tipo specificato, non quello con tutte le cifre esadecimali nel suo nome.


7

La risposta di Per @ Slauma e il suggerimento di @ Milton Ho esteso il metodo di salvataggio personalizzato della nostra classe base con un tentativo / cattura che gestirà (e quindi accederà alla nostra registrazione degli errori!) Questo tipo di eccezioni.

// Where `BaseDB` is your Entities object... (it could be `this` in a different design)
public void Save(bool? validateEntities = null)
{
    try
    {
        //Capture and set the validation state if we decide to
        bool validateOnSaveEnabledStartState = BaseDB.Configuration.ValidateOnSaveEnabled;
        if (validateEntities.HasValue)
            BaseDB.Configuration.ValidateOnSaveEnabled = validateEntities.Value;

        BaseDB.SaveChanges();

        //Revert the validation state when done
        if (validateEntities.HasValue)
            BaseDB.Configuration.ValidateOnSaveEnabled = validateOnSaveEnabledStartState;
    }
    catch (DbEntityValidationException e)
    {
        StringBuilder sb = new StringBuilder();
        foreach (var eve in e.EntityValidationErrors)
        {
            sb.AppendLine(string.Format("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:", 
                                            eve.Entry.Entity.GetType().Name,
                                            eve.Entry.State));
            foreach (var ve in eve.ValidationErrors)
            {
                sb.AppendLine(string.Format("- Property: \"{0}\", Error: \"{1}\"",
                                            ve.PropertyName,
                                            ve.ErrorMessage));
            }
        }
        throw new DbEntityValidationException(sb.ToString(), e);
    }
}

1
Puoi usare direttamente sb.AppendFormat ()
Bastien Vandamme il

1
Dovrai aggiungere anche la tua nuova riga se usi AppendFormat.
jocull,

7

Ho dovuto scrivere questo nella finestra immediata: 3

(((exception as System.Data.Entity.Validation.DbEntityValidationException).EntityValidationErrors as System.Collections.Generic.List<System.Data.Entity.Validation.DbEntityValidationResult>)[0].ValidationErrors as System.Collections.Generic.List<System.Data.Entity.Validation.DbValidationError>)[0]

per approfondire l'errore esatto!


6

Usando la risposta di @Slauma ho creato uno snippet di codice (un surround con snippet) per un migliore utilizzo.

<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <SnippetTypes>
        <SnippetType>SurroundsWith</SnippetType>
      </SnippetTypes>
      <Title>ValidationErrorsTryCatch</Title>
      <Author>Phoenix</Author>
      <Description>
      </Description>
      <HelpUrl>
      </HelpUrl>
      <Shortcut>
      </Shortcut>
    </Header>
    <Snippet>
      <Code Language="csharp"><![CDATA[try
{
    $selected$ $end$
}
catch (System.Data.Entity.Validation.DbEntityValidationException e)
{
    foreach (var eve in e.EntityValidationErrors)
    {
        Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
            eve.Entry.Entity.GetType().Name, eve.Entry.State);
        foreach (var ve in eve.ValidationErrors)
        {
            Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
                ve.PropertyName, ve.ErrorMessage);
        }
    }
    throw;
}]]></Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

5

Cattura l'eccezione in un tentativo di cattura e poi guarda rapidamente o ctrl + d & ctrl + q e puoi eseguire il drill down su EntityValidationErrors.


5

Sto solo gettando i miei due centesimi in ...

Nel mio dbConfiguration.cs, mi piace racchiudere il mio metodo.SaveChanges () in un metodo try / catch e produrre un file di testo di output che mi permette di leggere chiaramente gli errori, e questo codice li timestamp - utile se si incappare in più di un errore in momenti diversi!

        try
        {
            context.SaveChanges();
        }
        catch (DbEntityValidationException e)
        {
            //Create empty list to capture Validation error(s)
            var outputLines = new List<string>();

            foreach (var eve in e.EntityValidationErrors)
            {
                outputLines.Add(
                    $"{DateTime.Now}: Entity of type \"{eve.Entry.Entity.GetType().Name}\" in state \"{eve.Entry.State}\" has the following validation errors:");
                outputLines.AddRange(eve.ValidationErrors.Select(ve =>
                    $"- Property: \"{ve.PropertyName}\", Error: \"{ve.ErrorMessage}\""));
            }
            //Write to external file
            File.AppendAllLines(@"c:\temp\dbErrors.txt", outputLines);
            throw;
        }

5

Quello che ho trovato ... quando ho ricevuto l'errore 'EntityValidationErrors' è che .... ho un campo nel mio database 'db1' nella tabella 'tbladdress' come 'address1' che ha dimensioni 100 (cioè address varchar (100) null) e stavo passando un valore superiore a 100 caratteri..e questo portava ad un errore durante il salvataggio dei dati nel database ....

Quindi devi controllare i dati che stai passando al campo.


1
Apprezzo questa risposta perché in realtà mi ha aiutato a risolvere il mio errore. La tabella in cui stavo salvando nel mio db aveva tutte le not nullcolonne, quindi una volta aggiunti i dati a tutti gli elementi precedenti al mio non db.SaveChanges()ho ricevuto alcun errore.
BinaryJoe01

3

Questo funziona per me.

var modelState = ModelState.Values;
if (!ModelState.IsValid)
{
    return RedirectToAction("Index", "Home", model);
}

Inserisci un punto di interruzione sull'istruzione if. Quindi è possibile controllare modelState nelle finestre di debug. Su ogni valore puoi vedere se c'è un errore e persino il messaggio di errore. Questo è tutto. Quando non ti serve più, elimina o commenta la riga.

Spero che questo possa aiutare.

Se richiesto, posso fornire uno screenshot dettagliato nella finestra di debug.


3

Come menzionato in altri post, basta catturare l'eccezione nella classe DbEntityValidationException. Il che ti darà un vantaggio in caso di errori.

 try
 {
  ....
 }
 catch(DbEntityValidationException ex)
 {
  ....
 }

2

Ho riscontrato questo errore prima

quando ho provato ad aggiornare un campo specifico nel mio modello in framwork di entità

Letter letter = new Letter {ID = letterId, ExportNumber = letterExportNumber,EntityState = EntityState.Modified};
LetterService.ChangeExportNumberfor(letter);
//----------


public int ChangeExportNumber(Letter letter)
    {
        int result = 0;
        using (var db = ((LettersGeneratorEntities) GetContext()))
        {
            db.Letters.Attach(letter);
            db.Entry(letter).Property(x => x.ExportNumber).IsModified = true;
            result += db.SaveChanges();
        }
        return result;
    }

e secondo le risposte di cui sopra

Ho trovato il messaggio di convalida The SignerName field is required.

quale punta al campo nel mio modello

e quando ho controllato il mio schema di database ho trovato

inserisci qui la descrizione dell'immagine

così off coure ValidationExceptionha il diritto di aumentare

e secondo questo campo voglio che sia nulla, (non so come ho fatto un casino)

così ho modificato quel campo per consentire Null, e con questo il mio codice non mi darà più questo errore

quindi questo errore potrebbe verificarsi se si annulla l'integrità dei dati del database


1
Se qui debba essere sollevata o meno un'eccezione non è questo il punto. Quindi, stai tagliando alcuni angoli qui. Quando è richiesto un campo nello schema del database, è necessario più di quello per avere un valore DbEntityValidationExceptionrialzato.
Gert Arnold,

2

Controlla i valori dei campi che stai passando, sono validi e in base ai campi del database. Ad esempio, il numero di caratteri passati in un determinato campo è inferiore ai caratteri definiti nel campo della tabella del database.


1

Se stai usando IIS con Windows Authentification ed Entity Framework , fai attenzione authorize.

Ho provato a farlo POSTsenza autorizzazione e non ha funzionato, e ho riscontrato questo errore db.SaveChangesAsync();, mentre tutti gli altri verbi GETe DELETEfunzionavano.

Ma quando ho aggiunto AuthorizeAttribute come annotazione, ha funzionato.

[Authorize]
public async Task<IHttpActionResult> Post(...){
....
}

1

Ecco un altro modo per farlo invece di usare foreach loop per guardare dentro EntityValidationErrors. Ovviamente puoi formattare il messaggio a tuo piacimento:

try {
        // your code goes here...
    } 
catch (DbEntityValidationException ex) 
    {
        Console.Write($"Validation errors: {string.Join(Environment.NewLine, ex.EntityValidationErrors.SelectMany(vr => vr.ValidationErrors.Select(err => $"{err.PropertyName} - {err.ErrorMessage}")))}", ex);
        throw;
    }

1

Nel mio caso è stato a causa della lunghezza del campo del database inferiore alla lunghezza del campo di input.

tabella del database

create table user(
  Username nvarchar(5) not  null
);

Il mio contributo

User newUser = new User()
{
   Username = "123456"
};

il valore per Username lengthè 5 che è lessthan6

... questo può aiutare qualcuno


0

Verifica se hai un Not Nullvincolo nelle colonne della tabella e non stai passando il valore per quella colonna durante le operazioni di inserimento / aggiornamento. Ciò causa questa eccezione nel framework di entità.


0

Ho anche affrontato lo stesso problema. Ho aggiornato il mio .edmx dal database dopo che l'eccezione è svanita.


0

Questo errore si verifica principalmente a causa delle dimensioni del campo. CONTROLLARE tutte le dimensioni dei campi in una tabella del database.


0

Stavo anche lottando con questo errore e in base all'argomento qui e questa risposta è stata in grado di capire lo snippet da copiare / incollare senza la necessità di capire cosa deve essere importato (eccellente per i principianti di C #), codice qui sotto:

try
{
  context.SaveChanges();
}
catch (System.Data.Entity.Validation.DbEntityValidationException ex)
{
  foreach (var entityValidationErrors in ex.EntityValidationErrors)
  {
    foreach (var validationError in entityValidationErrors.ValidationErrors)
    {
      System.Diagnostics.Debug.WriteLine("Property: " + validationError.PropertyName + " Error: " + validationError.ErrorMessage);
    }
  }
}
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.