सत्यापन एक या अधिक संस्थाओं के लिए विफल रहा। अधिक विवरण के लिए 'EntityValidationErrors' संपत्ति देखें


804

कोड प्रथम एप्रोच के साथ अपने डेटाबेस को सीड करने पर मुझे यह त्रुटि हो रही है।

सत्यापन एक या अधिक संस्थाओं के लिए विफल रहा। अधिक विवरण के लिए 'EntityValidationErrors' संपत्ति देखें।

ईमानदार होने के लिए मुझे नहीं पता कि सत्यापन त्रुटियों की सामग्री की जांच कैसे करें। विजुअल स्टूडियो मुझे दिखाता है कि यह 8 ऑब्जेक्ट्स के साथ एक सरणी है, इसलिए 8 सत्यापन त्रुटियां हैं।

यह मेरे पिछले मॉडल के साथ काम कर रहा था, लेकिन मैंने कुछ बदलाव किए जो मैं नीचे समझाता हूं:

  • मेरे पास स्टेटस नाम की एक एनम थी, मैंने उसे स्टेटस नामक क्लास में बदल दिया
  • मैंने एक ही तालिका में 2 विदेशी कुंजी रखने के लिए कक्षा आवेदकों को बदल दिया है

मुझे लंबे कोड के लिए क्षमा करें, लेकिन मुझे यह सब पेस्ट करना होगा। अपवाद को निम्न कोड की अंतिम पंक्ति में फेंक दिया जाता है।

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

जवाबों:


1237

ईमानदार होने के लिए मुझे नहीं पता कि सत्यापन त्रुटियों की सामग्री की जांच कैसे करें। विजुअल स्टूडियो मुझे दिखाता है कि यह 8 ऑब्जेक्ट्स के साथ एक सरणी है, इसलिए 8 सत्यापन त्रुटियां हैं।

यदि आप डीबग के दौरान दृश्य स्टूडियो में उस सरणी में ड्रिल करते हैं तो वास्तव में आपको त्रुटियों को देखना चाहिए। लेकिन आप अपवाद को भी पकड़ सकते हैं और फिर त्रुटियों को कुछ लॉगिंग स्टोर या कंसोल पर लिख सकते हैं:

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एक संग्रह है जो उन संस्थाओं का प्रतिनिधित्व करता है जिन्हें सफलतापूर्वक सत्यापित नहीं किया जा सकता है, और ValidationErrorsप्रति इकाई आंतरिक संग्रह संपत्ति स्तर पर त्रुटियों की एक सूची है।

समस्या के स्रोत को खोजने के लिए ये सत्यापन संदेश आमतौर पर पर्याप्त सहायक होते हैं।

संपादित करें

कुछ मामूली सुधार:

मूल्य हमलावर संपत्ति का तो जैसे भीतरी पाश में शामिल किया जा सकता है:

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

हालांकि डिबगिंग Debug.Writeबेहतर हो सकती है Console.WriteLineक्योंकि यह सभी प्रकार के अनुप्रयोगों में काम करता है, न केवल कंसोल अनुप्रयोगों (नीचे टिप्पणी में उनके नोट के लिए @Bart के लिए धन्यवाद)।

वेब अनुप्रयोगों के लिए जो उत्पादन में हैं और अपवाद का उपयोग करने के लिए एल्माह का उपयोग करते हैं, यह मेरे लिए एक SaveChangesनया अपवाद बनाने के लिए एक कस्टम अपवाद बनाने और अधिलेखित करने के लिए बहुत उपयोगी साबित हुआ ।

कस्टम अपवाद प्रकार इस तरह दिखता है:

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

और SaveChangesनिम्नलिखित तरीके से लिखा जा सकता है:

public class MyContext : DbContext
{
    // ...

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

कुछ टिप्पणी:

  • पीला त्रुटि स्क्रीन जो एल्माह वेब इंटरफेस में या भेजे गए ईमेल में दिखाता है (यदि आपने उसे कॉन्फ़िगर किया है) अब सत्यापन विवरण को सीधे संदेश के शीर्ष पर प्रदर्शित करता है।

  • ओवरराइट करने Messageके बजाय अधिलेखन के कस्टम अपवाद में संपत्ति ToString()लाभ यह है कि मानक ASP.NET "मौत (YSOD) का पीला स्क्रीन" इस संदेश को प्रदर्शित करता है और साथ ही किया है। एल्माह के विपरीत YSOD स्पष्ट रूप से उपयोग नहीं करता है ToString(), लेकिन दोनों ही Messageसंपत्ति प्रदर्शित करते हैं।

  • मूल DbEntityValidationExceptionको आंतरिक अपवाद के रूप में लपेटना यह सुनिश्चित करता है कि मूल स्टैक ट्रेस अभी भी उपलब्ध होगा और एल्माह और वाईएसओडी में प्रदर्शित किया गया है।

  • लाइन पर एक ब्रेकपॉइंट सेट करके throw newException;आप केवल newException.Messageसत्यापन संग्रह में ड्रिलिंग के बजाय एक संपत्ति के रूप में संपत्ति का निरीक्षण कर सकते हैं जो थोड़ा अजीब है और सभी के लिए आसानी से काम नहीं करता है (नीचे टिप्पणियां देखें)।


87
अपवाद में ड्रिलिंग कुछ नहीं करता है। यह सिर्फ कहता है कि एक DbEntityValidationResult है लेकिन आपको विस्तार नहीं करने देता है !!
शुमि

30
@Shumii अपवाद का विस्तार करने के लिए यह उत्तर देखें ।
कैविन वॉनडेलेन

18
बस एक सुरुचिपूर्ण समाधान का विस्तार करने के लिए। आप अपने स्वयं के DbContext वर्ग में savechanges विधि को ओवरराइड करना चाह सकते हैं, और उसके बाद try पकड़ ब्लॉक को जोड़ सकते हैं, जहाँ कोशिश ब्लॉक बस (base.SaveChanges ()) को बचाने की कोशिश करता है, और पकड़ने वाला ब्लॉक केवल DEEntityValidationException को पकड़ता है। इस प्रकार, आपको अपने परिवर्तनों को सहेजने वाले प्रत्येक स्थान पर इसे जोड़ने की आवश्यकता नहीं है।
मिल्टन

7
इसने मेरे बेकन को एक से अधिक मौकों पर बचाया है। मैं केवल एक बार उत्थान कर सकता था। चाहता था कि वे मुझे हर बार मेरे द्वारा कॉपी किए गए और इसे चिपकाया जाए।
डेमन ड्रेक

5
+2 कोड के लिए। वास्तव में एक रक्षक :) -1 का उपयोग करने के लिए Console.WriteLine, मुझे लगता है कि अधिक लोग आजकल वेब परियोजनाओं को लिख रहे हैं, आजकल क्षुधा को सांत्वना देते हैं, और Debug.Writeदोनों में काम करते हैं ...
बार्ट

459

आप इसे किसी भी कोड को लिखे बिना डिबगिंग के दौरान विजुअल स्टूडियो से कर सकते हैं, यहां तक ​​कि कैच ब्लॉक भी नहीं।

बस नाम के साथ एक घड़ी जोड़ें:

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

घड़ी की अभिव्यक्ति $exceptionवर्तमान संदर्भ में फेंके गए किसी भी अपवाद को प्रदर्शित करती है, भले ही इसे पकड़ा नहीं गया हो और एक चर को सौंपा गया हो।

Http://mattrandle.me/viewing-entityvalidationerrors-in-visual-studio/ पर आधारित


39
+1 वे बेहतर समाधान, और कोड में परिवर्तन की आवश्यकता नहीं है। कूल
जस्टास

4
+1 यह बहुत, बहुत आसान है! तुम भी एक कोशिश / पकड़ ब्लॉक की जरूरत नहीं है। बस इसे वॉच लिस्ट में रखें जब वीएस टूटता है और वॉयला होता है .. आपके सामने सत्यापन की त्रुटियां हैं।
वेइतिमान

40
साल में एक दो बार मैं भूल जाता हूं कि यह कैसे करना है और इस उत्तर को ढूंढना है
जस्टिन मूर

3
@ ज़ीरजा मैंने इसे vb.net में परीक्षण नहीं किया है, लेकिन ऐसा प्रतीत होता है कि चर को vb.net के साथ-साथ msdn.microsoft.com/en-us/library/ms164891.aspx में परिभाषित किया गया है , हालांकि कलाकार शायद नहीं हैं vb.net के लिए परिभाषित किया गया है, और इसके बजाय आपको शायद DirectCast ($ अपवाद, System.Data.Entity.Validation.DbEntityValidationException) करना चाहिए
योएल हैल्ब

2
मुझे पता है कि टिप्पणियों में "धन्यवाद" का स्वागत नहीं है, लेकिन मुझे समय बर्बाद करने से रोकने के लिए ... धन्यवाद!
लूथर

105

यह वास्तव में कोड लिखने के बिना कर सकता है:

अपने कैच ब्लॉक में, कोड के निम्नलिखित लाइन पर एक ब्रेक प्वाइंट जोड़ें:

catch (Exception exception)
{

}

अब यदि आप इस पर मंडराते हैं exceptionया इसे जोड़ते हैं Watchऔर फिर नीचे दिखाए अनुसार अपवाद विवरणों में नेविगेट करते हैं; आप देखेंगे कि कौन सा विशेष कॉलम है () समस्या का कारण बन रहे हैं क्योंकि यह त्रुटि आमतौर पर तब होती है जब तालिका-बाधा का उल्लंघन किया जाता है।

यहां छवि विवरण दर्ज करें

बड़ी छवि


4
यह दृष्टिकोण बहुत सरल है और आईडीई :) का लाभ
उठाता है

3
यह एक अच्छा समाधान है क्योंकि यह त्वरित, सरल है, आईडीई का उपयोग करता है, और मुझे एक टन समय बचाता है।
मैक्सशूट

2
मुझे इस तरह से पसंद है "कोड कैसे करना है और कोड नहीं करना है"
खुला और मुफ्त

1
धन्यवाद। यह सरल है, लेकिन आईडीई का उपयोग करके अपवाद को देखना शानदार है।
थॉमस.बेंज

सही समाधान
नीरज सिंह चौहान

46

यहां बताया गया है कि आप आईडीई में डीबगिंग के दौरान विजुअल स्टूडियो (किसी भी अतिरिक्त कोड को लिखे बिना) में EntityValidationErrors की सामग्री की जांच कैसे कर सकते हैं ।

समस्या?

आप सही हैं, Visual Studio डीबगर का विवरण विवरण पॉपअप EntityValidationErrorsसंग्रह के अंदर वास्तविक त्रुटियों को नहीं दिखाता है ।

यहां छवि विवरण दर्ज करें

समाधान!

बस क्विक वॉच विंडो में निम्न अभिव्यक्ति जोड़ें और पुनर्मूल्यांकन पर क्लिक करें ।

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

मेरे मामले में, देखें कि मैं संग्रह के ValidationErrors Listअंदर कैसे विस्तार कर पा रहा हूंEntityValidationErrors

यहां छवि विवरण दर्ज करें

संदर्भ: matrandle.me ब्लॉग पोस्ट , @ योएल का जवाब


3
यह क्यों तय नहीं किया गया है? यह त्रुटि को कुछ और नहीं दिखाना चाहिए
जिओमोरिलो

2
सत्यापन त्रुटि संपत्ति त्रुटि दिखाती है, पूर्व। विषय क्षेत्र की आवश्यकता है, अच्छा उत्तर, धन्यवाद
हम्जे.धनदेव

1
महान! इसने मेरी रात बचाई! :)
पैट्रिक

1
यह देखने में सटीक त्रुटि की कल्पना करने का स्मार्ट तरीका है ... धन्यवाद!
क्वर्टी

39

पहली त्रुटि को देखने के बिना एक घड़ी जोड़ने के बिना भी आप तत्काल विंडो में इसे पेस्ट कर सकते हैं:

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

1
आप सभी को पाने के लिए $ अपवाद का उपयोग भी कर सकते हैं। EntityValidationErrors.SelectMany (x => x.ValidationErrors) .Select (x => x.ErrorMessage) उन सभी को पाने के लिए :) तत्काल खिड़की का उपयोग करके सबसे अच्छा जवाब है
chrispepper1989

15

में काम करने वाले किसी के लिए भी 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

जब आप catch {...}ब्लॉक में डिबग मोड में होते हैं, तो "क्विकवेच" विंडो ( ctrl+ alt+ q) खोलें और वहां पेस्ट करें:

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

या:

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

यदि आप एक कोशिश में नहीं हैं / पकड़ या अपवाद वस्तु तक पहुँच नहीं है।

यह आपको ValidationErrorsपेड़ में नीचे ड्रिल करने की अनुमति देगा । इन त्रुटियों में त्वरित जानकारी प्राप्त करना सबसे आसान तरीका है।


10

यदि आप केवल एक सामान्य अपवाद को पकड़ रहे हैं, तो यह आपको DbEntityValidationException के रूप में कास्ट करने के लिए लाभ दे सकता है । इस प्रकार के अपवाद में एक वैधता त्रुटि संपत्ति है, और अपने तरीके से उनमें विस्तार करने के लिए जारी है, आपको सभी समस्याएं मिलेंगी।

उदाहरण के लिए, यदि आप पकड़ में विराम बिंदु डालते हैं, तो आप निम्नलिखित को एक घड़ी में फेंक सकते हैं:

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

एक त्रुटि का एक उदाहरण है यदि कोई फ़ील्ड नल की अनुमति नहीं देता है, और आपके पास एक नल स्ट्रिंग है, तो आप देखेंगे कि यह कहता है कि फ़ील्ड आवश्यक है।


9

बस अपने डेटाबेस तालिका फ़ील्ड लंबाई की जाँच करें। आपका इनपुट पाठ स्तंभ फ़ील्ड डेटा प्रकार की लंबाई से अधिक बड़ा है


9

डिबग में, आप इसे अपने क्विकवॉच एक्सप्रेशन मूल्यांकनकर्ता प्रविष्टि क्षेत्र में दर्ज कर सकते हैं:

context.GetValidationErrors()

8

@Slauma से जवाब वास्तव में बहुत अच्छा है, लेकिन मैंने पाया कि यह तब काम नहीं करता था जब एक कॉम्पलेक्स टाइप संपत्ति अवैध थी।

उदाहरण के लिए, मान लें कि आपके पास Phoneजटिल प्रकार की संपत्ति है PhoneNumber। यदि AreaCodeसंपत्ति अमान्य है, तो संपत्ति का नाम ve.PropertyNames"Phone.AreaCode" है। इसके कारण कॉल eve.Entry.CurrentValues<object>(ve.PropertyName)विफल हो जाती है।

इसे ठीक करने के लिए, आप प्रत्येक पर संपत्ति के नाम को विभाजित कर सकते हैं ., फिर संपत्ति के नाम के परिणामी सरणी के माध्यम से पुनरावृत्ति कर सकते हैं। अंत में, जब आप श्रृंखला में सबसे नीचे आते हैं, तो आप बस संपत्ति के मूल्य को वापस कर सकते हैं।

FormattedDbEntityValidationExceptionकॉम्प्लेक्सटेप्स के समर्थन के साथ नीचे @ सलुमा की कक्षा है।

का आनंद लें!

[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
मैं विश्वास नहीं कर सकता कि अधिक लोगों ने इसे एक नहीं बनाया है, क्योंकि यह एक बहुत ही वास्तविक परिदृश्य है और यह मुझे पिछले दो रातों से चला रहा है। आप जानते हैं कि जब आप अपनी त्रुटि से निपटने का एहसास करते हैं तो आपको लगता है कि वास्तव में त्रुटि क्या है? ओह।
डीजे ग्रॉसमैन

7

ध्यान दें कि Entity.GetType().BaseType.Nameआपके द्वारा निर्दिष्ट प्रकार का नाम, इसके नाम के सभी हेक्स अंकों के साथ नहीं।


7

@ Slauma के उत्तर और @ मिल्टन के सुझाव के अनुसार, हमने अपने बेस क्लास के कस्टम सेव मेथड को एक कोशिश / कैच के साथ बढ़ाया है जो हैंडल करेगा (और इसलिए हमारी त्रुटि लॉगिंग में लॉग इन करेगा!) इस प्रकार के अपवाद हैं।

// 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
आप sb.AppendFormat (सीधे उपयोग कर सकते हैं)
Bastien Vandamme

1
यदि आप AppendFormat का उपयोग करते हैं तो आपको अपनी खुद की नईलाइन भी जोड़ने की आवश्यकता होगी।
jocull

7

मुझे इसे तत्काल विंडो: 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]

सटीक त्रुटि में गहरी पाने के लिए!


6

@Slauma के उत्तर का उपयोग करके मैंने बेहतर उपयोग के लिए एक कोड स्निपेट (स्निपेट के साथ एक घेर) बनाया है।

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

एक कोशिश पकड़ में अपवाद को पकड़ने और फिर त्वरित घड़ी या ctrl + d & ctrl + q और आप नीचे EntityValidationErrors को ड्रिल कर सकते हैं।


5

बस मेरे दो सेंट फेंकने में ...

मेरे dbConfiguration.cs के भीतर, मैं अपने संदर्भ को लपेटना पसंद करता हूं। किसी भी कोशिश / कैच में एक विधि टेक्स्ट फ़ाइल का उत्पादन करने के लिए मुझे एक त्रुटि पाठ (एस) को पढ़ने की अनुमति देता है, और यह कोड उन्हें टाइमस्टैम्प भी करता है - यदि आप अलग-अलग समय में एक से अधिक त्रुटियों में चलाएं!

        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

मुझे क्या मिला ... जब मुझे 'EntityValidationErrors' त्रुटि मिली है .... मेरे पास अपने डेटाबेस 'db1' में एक फ़ील्ड है तालिका 'tbladdress' में 'address1' के रूप में जिसका आकार 100 है (अर्थात पता )char (100) null) और मैं 100 से अधिक वर्ण मान रहा था..और डेटाबेस में डेटा सहेजते समय यह त्रुटि के लिए अग्रणी था ...।

इसलिए आपको उस डेटा की जांच करनी चाहिए जो आप क्षेत्र में पास कर रहे हैं।


1
मैं इस उत्तर की सराहना करता हूं क्योंकि इसने वास्तव में मेरी त्रुटि को हल करने में मेरी मदद की। जिस तालिका में मैं अपने db में बचत कर रहा था, उसमें सभी not nullकॉलम थे, इसलिए एक बार जब मैंने db.SaveChanges()कोई त्रुटि प्राप्त की, उससे पहले मैंने सभी तत्वों में डेटा जोड़ दिया ।
बाइनरीजियो 01

3

यह मेरे लिए काम करता है।

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

अगर स्टेटमेंट पर ब्रेकपॉइंट लगाएं। तब आप डिबग विंडो में मॉडलस्टैट की जांच कर सकते हैं। हर मूल्य पर आप देख सकते हैं कि क्या कोई त्रुटि है और यहां तक ​​कि त्रुटि संदेश भी। बस। जब आपको इसकी आवश्यकता नहीं है, तो बस लाइन को हटा दें या टिप्पणी करें।

मुझे उम्मीद है कि इससे सहायता मिलेगी।

अगर पूछा जाए, तो मैं डिबग विंडो में विस्तृत स्क्रीनशॉट प्रदान कर सकता हूं।


3

जैसा कि अन्य पोस्ट में बताया गया है, केवल DbEntityValidationException वर्ग में अपवाद को पकड़ें। जो आपको त्रुटि मामलों के दौरान आपको आवश्यक छूट प्रदान करेगा।

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

2

मुझे इस त्रुटि का सामना करना पड़ा

जब मैंने अपने मॉडल में इकाई फ्रेमवर्क में विशिष्ट क्षेत्र को अपडेट करने की कोशिश की

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

और उपरोक्त उत्तरों के अनुसार

मुझे मान्यता संदेश मिला The SignerName field is required.

जो मेरे मॉडल में क्षेत्र की ओर इशारा करता है

और जब मैंने अपने डेटाबेस स्कीमा की जाँच की तो मैंने पाया

यहां छवि विवरण दर्ज करें

इसलिए बंद ValidationExceptionको बढ़ाने का अधिकार है

और इस क्षेत्र के अनुसार मैं इसे अशक्त होना चाहता हूं, (मुझे नहीं पता कि मैंने इसे कैसे गड़बड़ कर दिया)

इसलिए मैंने नल को अनुमति देने के लिए उस फ़ील्ड को बदल दिया, और इसके द्वारा मेरा कोड मुझे यह त्रुटि दोबारा नहीं देगा

इसलिए यह त्रुटि हो सकती है यदि आप अपने डेटाबेस की डेटा अखंडता को अमान्य करते हैं


1
कोई अपवाद उठाया जाना चाहिए या नहीं, यहां बात नहीं है। अगला, आप यहां कुछ कोनों को काट रहे हैं। जब डेटाबेस स्कीमा में फ़ील्ड की आवश्यकता होती है तो आपको एक से अधिक की आवश्यकता होती है DbEntityValidationException
गर्ट अर्नोल्ड

2

कृपया उन फ़ील्ड मान की जाँच करें जो आप पास कर रहे हैं, मान्य हैं और डेटाबेस फ़ील्ड के अनुसार हैं। उदाहरण के लिए किसी विशेष क्षेत्र में पारित वर्णों की संख्या डेटाबेस तालिका क्षेत्र में परिभाषित वर्णों से कम है।


1

यदि आप Windows प्रमाणीकरण और इकाई ढांचे के साथ IIS का उपयोग कर रहे हैं , तो उपयोग करने के लिए सावधान रहें ।authorize

मैंने POSTअधिकृत किए बिना करने की कोशिश की और यह काम नहीं किया, और यह त्रुटि प्राप्त की db.SaveChangesAsync();, जबकि अन्य सभी क्रियाएं GETऔर DELETEकाम कर रही थीं।

लेकिन जब मैंने प्राधिकरण को एनोटेशन के रूप में जोड़ा, तो यह काम कर गया।

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

1

EntityValidationErrors के अंदर फ़ॉरच लूप का उपयोग करने के बजाय इसे करने का एक और तरीका है। बेशक आप अपनी पसंद के अनुसार संदेश को प्रारूपित कर सकते हैं:

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

मेरे मामले में ऐसा इसलिए था क्योंकि डेटाबेस फ़ील्ड की लंबाई इनपुट फ़ील्ड की लंबाई से कम है।

डेटाबेस तालिका

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

मेरा इनपुट

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

के लिए मूल्य Username lengthहै 5 जो lessthan6

... इससे किसी की मदद हो सकती है


0

जांचें कि क्या Not Nullआपके टेबल कॉलम में आपको अड़चन है और आप ऑपरेशनों को सम्मिलित / अपडेट करते समय उस कॉलम के लिए मान पास नहीं कर रहे हैं। कि इस अपवाद को इकाई ढांचे में रखा गया है।


0

मैंने भी उसी समस्या का सामना किया। मैंने अपने .edmx को डेटाबेस से अपडेट किया, उसके बाद अपवाद गायब हो गया।


0

यह त्रुटि ज्यादातर फ़ील्ड आकार के कारण होती है। डेटाबेस तालिका में सभी फ़ील्ड आकारों को चेक करें।


0

इस त्रुटि से भी जूझ रहा था और यहाँ विषय पर आधारित था और यह उत्तर स्निपेट को कॉपी / पेस्ट करने की आवश्यकता के बिना पता लगाने में सक्षम था कि क्या आयात किया जाना है (सी # शुरुआती के लिए उत्कृष्ट), नीचे कोड:

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);
    }
  }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.