877 votes

La validation a échoué pour une ou plusieurs entités. Voir ' EntityValidationErrors ' propriété pour plus de détails

Je vais avoir cette erreur lors de l'ensemencement de ma base de données avec le code de la première approche.

La Validation a échoué pour une ou plusieurs entités. Voir " EntityValidationErrors la propriété pour plus de détails.

Pour être honnête, je ne sais pas comment vérifier le contenu des erreurs de validation, Visual Studio me montre que c'est un tableau de 8 objets. 8 Erreurs de validation.

C'était avec mon modèle précédent, mais j'ai fait quelques changements que j'explique ci-dessous: - J'ai eu un enum appelé État, je l'ai changé pour une classe appelée État de - J'ai modifié la classe ApplicantsPositionHistory pour avoir 2 clés étrangères à la même table

Excusez-moi pour le long code, mais je dois coller tout. L'exception est levée dans la dernière ligne du code ci-dessous.

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

1351voto

Slauma Points 76561

Pour être honnête, je ne sais pas comment faire pour vérifier le contenu de la validation les erreurs, Visual Studio me montre que c'est un tableau de 8 objets. donc 8 les Erreurs de validation.

En fait, vous devriez voir les erreurs, si vous percez dans ce tableau dans Visual studio cours de débogage. Mais vous pouvez aussi attraper l'exception, puis d'écrire les erreurs de certains enregistrement du magasin ou de la 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 est une collection qui représente les entités qui ne pouvaient pas être validé, et l'intérieur de la collection ValidationErrors par entité est une liste d'erreurs sur le niveau de la propriété.

Ces messages de validation sont généralement de les aider à trouver la source du problème.

Modifier

Quelques légères améliorations:

La valeur de la propriété fautive peut être inclus dans la boucle interne de la sorte:

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

Lors du débogage Debug.Write pourrait être préférable à d' Console.WriteLine qu'il fonctionne dans tout type d'applications, non seulement les applications de console (merci à @Bart de sa note dans les commentaires ci-dessous).

Pour les applications web qui sont dans la production et l'utilisation d'un Elmah pour l'enregistrement d'exception, il s'est avéré être très utile pour moi de créer une exception personnalisée et écraser SaveChanges afin de lancer cette nouvelle exception.

Le type d'exception personnalisé ressemble à ceci:

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

Et SaveChanges peut être remplacé de la manière suivante:

public class MyContext : DbContext
{
    // ...

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

Quelques remarques:

  • Le jaune d'erreur de l'écran que Elmah affiche dans l'interface web ou dans les e-mails envoyés (si vous avez configuré) affiche désormais la validation de détails directement en haut du message.

  • L'écrasement de l' Message de la propriété à l'exception personnalisée au lieu de l'écraser ToString() a l'avantage que la norme ASP.NET "le Jaune de l'écran de la mort (YSOD)" affiche ce message. Contrairement à Elmah la YSOD apparemment ne pas utiliser ToString(), mais à la fois d'afficher le Message de la propriété.

  • Emballage originale DbEntityValidationException - intérieure exception assure que l'original de la trace de la pile sera toujours disponible et est affiché dans Elmah et la YSOD.

  • En définissant un point d'arrêt sur la ligne, throw newException; vous pouvez simplement examiner l' newException.Message de la propriété comme un texte à la place de forage dans la validation des collections qui est un peu maladroit et ne semble pas un travail facile pour tout le monde (voir les commentaires ci-dessous).

497voto

yo hal Points 1949

Vous pouvez le faire depuis visual studio lors du débogage sans écrire de code, pas même un bloc catch.

Il suffit d’ajouter une montre avec le nom``

L’expression espionne « $exception » affiche toute exception levée dans le contexte actuel, même si elle n’a pas été attrapé et assigné à une variable.

Basé sur http://mattrandle.me/viewing-entityvalidationerrors-in-visual-studio/

118voto

t_plusplus Points 452

Cela pourrait effectivement le faire sans avoir à écrire du code :

Dans votre bloc catch procédez comme suit :

Maintenant si vous placez le curseur sur l’exception ou l’ajouter à la montre et puis naviguez dans les détails de l’exception, comme indiqué ci-dessous, vous verrez quelles colonnes particulière sont / sont la cause du problème que cette erreur se produit généralement lorsqu’une contrainte de table est voilated...

enter image description here

41voto

djdmbrwsk Points 11

Un moyen rapide de voir la première erreur sans même y ajouter une montre, vous pouvez coller ceci dans la fenêtre exécution :

17voto

nghiavt Points 98

pour tous ceux qui travaillent en VB.NET

Essayez

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X