इकाई फ्रेमवर्क का उपयोग करते हुए SQL सर्वर डेटाबेस में परिवर्तन को सहेजते समय सत्यापन एक या अधिक संस्थाओं के लिए विफल रहा


337

मैं अपने संपादन डेटाबेस में सहेजना चाहता हूं और मैं ASP.NET MVC 3 / C # में Entity फ़्रेमवर्क कोड-प्रथम का उपयोग कर रहा हूं, लेकिन मुझे त्रुटियां मिल रही हैं। मेरे ईवेंट क्लास में, मेरे पास डेटटाइम और टाइमस्पैन डेटाटाइप्स हैं, लेकिन मेरे डेटाबेस में, मुझे क्रमशः दिनांक और समय मिल गया है। क्या इसका कारण हो सकता है? डेटाबेस में परिवर्तन करने से पहले मैं कोड में उपयुक्त डेटाटाइप को कैसे कर सकता हूं।

public class Event
{
    public int EventId { get; set; }
    public int CategoryId { get; set; }
    public int PlaceId { get; set; }
    public string Title { get; set; }
    public decimal Price { get; set; }
    public DateTime EventDate { get; set; }
    public TimeSpan StartTime { get; set; }
    public TimeSpan EndTime { get; set; }
    public string Description { get; set; }
    public string EventPlaceUrl { get; set; }
    public Category Category { get; set; }
    public Place Place { get; set; }
}

नियंत्रक में विधि >>>> storeDB पर समस्या ।aveChanges ();

// POST: /EventManager/Edit/386        
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
    var theEvent = storeDB.Events.Find(id);

    if (TryUpdateModel(theEvent))
    {
        storeDB.SaveChanges();
        return RedirectToAction("Index");
    }
    else
    {
        ViewBag.Categories = storeDB.Categories.OrderBy(g => g.Name).ToList();
        ViewBag.Places = storeDB.Places.OrderBy(a => a.Name).ToList();
        return View(theEvent);
    }
}

साथ में

public class EventCalendarEntities : DbContext
{
    public DbSet<Event> Events { get; set; }
    public DbSet<Category> Categories { get; set; }
    public DbSet<Place> Places { get; set; } 
}

SQL Server 2008 R2 डेटाबेस / T-SQL

EventDate (Datatype = date)  
StartTime (Datatype = time)  
EndTime (Datatype = time)  

Http फॉर्म

EventDate (Datatype = DateTime) e.g. 4/8/2011 12:00:00 AM  
StartTime (Datatype = Timespan/time not sure) e.g. 08:30:00  
EndTime (Datatype = Timespan/time not sure) e.g. 09:00:00  

/ 'अनुप्रयोग में सर्वर त्रुटि

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

विवरण: वर्तमान वेब अनुरोध के निष्पादन के दौरान एक अनियंत्रित अपवाद हुआ। कृपया त्रुटि के बारे में अधिक जानकारी के लिए स्टैक ट्रेस की समीक्षा करें और यह कोड में कहां उत्पन्न हुआ।

अपवाद विवरण: System.Data.Entity.Validation.DbEntityValidationException: सत्यापन एक या अधिक संस्थाओं के लिए विफल हुआ। अधिक विवरण के लिए 'EntityValidationErrors' संपत्ति देखें।

स्रोत त्रुटि:

Line 75:             if (TryUpdateModel(theEvent))
Line 76:             {
Line 77:                 storeDB.SaveChanges();
Line 78:                 return RedirectToAction("Index");
Line 79:             }

स्रोत फ़ाइल: C: \ sep \ MvcEventCalendar \ MvcEventCalendar \ Controllers \ EventManagerController.cs लाइन: 77

स्टैक ट्रेस:

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


8
शायद आपके आवश्यक क्षेत्रों में से एक में एक शून्य मान है। जैसे EventDate, StartTime, Price, Category आदि
डेवो

क्या आपने डेटाबेस परिभाषित प्रकार से मेल खाने वाले प्रत्येक मैच को सुनिश्चित करने के लिए फॉर्म चर का निरीक्षण किया है? या जैसा डेवू ने कहा, आवश्यक रूप मूल्यों में से एक गायब है ...
टाइमोथाइक्लिफर्ड

डेटाबेस के प्रकार के साथ सभी पोस्ट किए गए फॉर्म चर नहीं मिलते हैं। मैंने डेटाबेस में दिनांक और समय का उपयोग किया है, लेकिन .NET में कोई प्रत्यक्ष डेटा टाइप नहीं है। इसलिए, मैंने DateTime और TimeSpan का उपयोग किया। अब मुझे क्रमशः दो और तारीख और समय बदलने की आवश्यकता है।
user522767

मेरे लिए त्रुटि का स्रोत एक स्ट्रिंग फ़ील्ड था जिसमें 30 से अधिक चार्ट हैं और डेटाबेस में मेरे फ़ील्ड का आकार 30 था।
Mojtaba

जवाबों:


840

आप DbEntityValidationExceptionनिम्नलिखित कोड से सभी जानकारी निकाल सकते हैं (आपको नामस्थान जोड़ने की आवश्यकता है: System.Data.Entity.Validationऔर System.Diagnosticsआपकी usingसूची में):

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

7
यदि कोई बीज डेटा पूरी तरह से मॉडल विशेषता नियमों (जैसे Required) को संतोषजनक नहीं है, तो आप यह त्रुटि भी प्राप्त कर सकते हैं । मैंने थोड़ा और जानकारी के साथ एक उत्तर जोड़ा है।
दान रिचारडसन

8
उत्तर यह बताकर सुधारा जा सकता है कि आप वास्तव में ट्रेस आउटपुट कहाँ देख सकते हैं।
मटकाजा

1
मुझे यह msdn लेख ट्रेस बहुत उपयोगी होने के बारे में मिला
बोरिक

2
आपने सर, इंटरनेट जीता।
लिएंड्रो

8
ट्रेस आउटपुट आउटपुट विंडो में देखा जा सकता है। शीर्ष पर डिबग पर क्लिक करें -> विंडोज -> आउटपुट
reggaeguitar

249

कोई कोड परिवर्तन आवश्यक:

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

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

या:

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

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

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


6
आप मेरे दोस्त एक जीनियस हैं, कि आपने मुझे मिली ईटी की त्रुटि का पता लगाने में मदद की, धन्यवाद!
मार्क क्रैम

4
कोई बात नहीं :) लेकिन एक जीनियस नहीं, बस क्विकवॉच से प्यार करें :)
गॉनियाल

4
केवल उन लोगों के लिए उत्तर को अपडेट किया है जिनके पास अपवाद ऑब्जेक्ट / चर तक पहुंच नहीं है।
गोनैले

7
जब भी मुझे यह अपवाद मिलता है मैं त्रुटि के लिए खोज करता हूं, तो मैं यहां (Google पर दूसरा परिणाम) आता हूं, मुझे यह पोस्ट मिलती है और मैं डीबग> वॉच पैनल में दूसरे समाधान का उपयोग करता हूं। दर्जनों बार किया। धन्यवाद गोनाले।
एटा एस।

1
क्या मैं केवल वही हूं जिसे "क्वेरी में अपवाद" का नाम वर्तमान संदर्भ में मौजूद नहीं है?
एलेक्स क्लॉज़

37

यदि आपके पास समान संपत्ति के नाम वाली कक्षाएं हैं, तो यहां प्रवीण के उत्तर का एक छोटा विस्तार है:

 catch (DbEntityValidationException dbEx)
 {
    foreach (var validationErrors in dbEx.EntityValidationErrors)
    {
       foreach (var validationError in validationErrors.ValidationErrors)
       {
          Trace.TraceInformation(
                "Class: {0}, Property: {1}, Error: {2}",
                validationErrors.Entry.Entity.GetType().FullName,
                validationError.PropertyName,
                validationError.ErrorMessage);
       }
    }
 }

22

प्रवीण और टोनी दोनों में सुधार के रूप में, मैं एक ओवरराइड का उपयोग करता हूं:

public partial class MyDatabaseEntities : DbContext
{
    public override int SaveChanges()
    {
        try
        {
            return base.SaveChanges();
        }
        catch (DbEntityValidationException dbEx)
        {
            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {
                    Trace.TraceInformation("Class: {0}, Property: {1}, Error: {2}",
                        validationErrors.Entry.Entity.GetType().FullName,
                        validationError.PropertyName,
                        validationError.ErrorMessage);
                }
            }

            throw;  // You can also choose to handle the exception here...
        }
    }
}

6

विस्तार पाठ के साथ अपवाद के लिए यह कार्यान्वयन रैप इकाई अपवाद है। यह संभालती है DbEntityValidationException, DbUpdateException, datetime2(उपयोगी है जब एक पर savind कई संस्थाओं रेंज त्रुटियों (एमएस एसक्यूएल), और संदेश में अमान्य संस्था की कुंजी शामिल SaveChangesकॉल)।

सबसे पहले, SaveChangesDbContext वर्ग में ओवरराइड करें :

public class AppDbContext : DbContext
{
    public override int SaveChanges()
    {
        try
        {
            return base.SaveChanges();
        }
        catch (DbEntityValidationException dbEntityValidationException)
        {
            throw ExceptionHelper.CreateFromEntityValidation(dbEntityValidationException);
        }
        catch (DbUpdateException dbUpdateException)
        {
            throw ExceptionHelper.CreateFromDbUpdateException(dbUpdateException);
        }
    }   

    public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken)
    {
        try
        {
            return await base.SaveChangesAsync(cancellationToken);
        }
        catch (DbEntityValidationException dbEntityValidationException)
        {
            throw ExceptionHelper.CreateFromEntityValidation(dbEntityValidationException);
        }
        catch (DbUpdateException dbUpdateException)
        {
            throw ExceptionHelper.CreateFromDbUpdateException(dbUpdateException);
        }
    }

अपवादग्राहक श्रेणी:

public class ExceptionHelper
{
    public static Exception CreateFromEntityValidation(DbEntityValidationException ex)
    {
        return new Exception(GetDbEntityValidationMessage(ex), ex);
    }

    public static string GetDbEntityValidationMessage(DbEntityValidationException ex)
    {
        // Retrieve the error messages as a list of strings.
        var errorMessages = ex.EntityValidationErrors
            .SelectMany(x => x.ValidationErrors)
            .Select(x => x.ErrorMessage);

        // Join the list to a single string.
        var fullErrorMessage = string.Join("; ", errorMessages);

        // Combine the original exception message with the new one.
        var exceptionMessage = string.Concat(ex.Message, " The validation errors are: ", fullErrorMessage);
        return exceptionMessage;
    }

    public static IEnumerable<Exception> GetInners(Exception ex)
    {
        for (Exception e = ex; e != null; e = e.InnerException)
            yield return e;
    }

    public static Exception CreateFromDbUpdateException(DbUpdateException dbUpdateException)
    {
        var inner = GetInners(dbUpdateException).Last();
        string message = "";
        int i = 1;
        foreach (var entry in dbUpdateException.Entries)
        {
            var entry1 = entry;
            var obj = entry1.CurrentValues.ToObject();
            var type = obj.GetType();
            var propertyNames = entry1.CurrentValues.PropertyNames.Where(x => inner.Message.Contains(x)).ToList();
            // check MS SQL datetime2 error
            if (inner.Message.Contains("datetime2"))
            {
                var propertyNames2 = from x in type.GetProperties()
                                        where x.PropertyType == typeof(DateTime) ||
                                            x.PropertyType == typeof(DateTime?)
                                        select x.Name;
                propertyNames.AddRange(propertyNames2);
            }

            message += "Entry " + i++ + " " + type.Name + ": " + string.Join("; ", propertyNames.Select(x =>
                string.Format("'{0}' = '{1}'", x, entry1.CurrentValues[x])));
        }
        return new Exception(message, dbUpdateException);
    }
}

यदि आप अपवाद को संभालना चाहते हैं, तो आपको SaveChangesAsync कॉल का इंतजार करना चाहिए।
अर्नब चक्रवर्ती

धन्यवाद, अर्नब चक्रवर्ती ! उत्तर तय
सेल

5

इस कोड ने मेरी समस्या का पता लगाने में मदद की जब मैंने अपने एंटिटी वैलीडेशन एरोस के साथ समस्या की थी। इसने मुझे अपनी इकाई परिभाषा के साथ सटीक समस्या बताई। निम्नलिखित कोड का प्रयास करें जहां आपको storeDB को कवर करने की आवश्यकता है ।aveChanges (); निम्नलिखित में पकड़ने की कोशिश ब्लॉक।

  try
{
         if (TryUpdateModel(theEvent))
         {
             storeDB.SaveChanges();
             return RedirectToAction("Index");
         }
}
catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
{
    Exception raise = dbEx;
    foreach (var validationErrors in dbEx.EntityValidationErrors)
    {
        foreach (var validationError in validationErrors.ValidationErrors)
        {
            string message = string.Format("{0}:{1}", 
                validationErrors.Entry.Entity.ToString(),
                validationError.ErrorMessage);
            // raise a new exception nesting
            // the current instance as InnerException
            raise = new InvalidOperationException(message, raise);
        }
    }
    throw raise;
}

4

मुझे आज यह त्रुटि मिल रही थी और कुछ समय तक यह काम नहीं कर सका, लेकिन मुझे लगा कि यह RequireAttributeमेरे मॉडल में कुछ एस जोड़ने के बाद है और कुछ विकास के बीज डेटा सभी आवश्यक क्षेत्रों को आबाद नहीं कर रहा है।
तो बस एक ध्यान दें कि यदि आपको यह त्रुटि किसी प्रकार की init रणनीति के माध्यम से डेटाबेस को अपडेट करते समय मिल रही है, DropCreateDatabaseIfModelChangesतो आपको यह सुनिश्चित करना होगा कि आपका बीज डेटा किसी भी मॉडल डेटा सत्यापन विशेषताओं को पूरा और संतुष्ट करता है

मुझे पता है कि यह सवाल में समस्या से थोड़ा अलग है, लेकिन यह एक लोकप्रिय सवाल है इसलिए मैंने सोचा कि मैं दूसरों के लिए खुद के समान मुद्दे के जवाब में थोड़ा और जोड़ दूंगा।
आशा है कि यह दूसरों की मदद करता है :)


4

मुझे लगता है कि हर SaveChanges()ऑपरेशन के लिए ट्राइ / कैच को जोड़ना एक अच्छा अभ्यास नहीं है, इसे केंद्रीकृत करना बेहतर है:

इस वर्ग को मुख्य DbContextवर्ग में जोड़ें :

public override int SaveChanges()
{
    try
    {
        return base.SaveChanges();
    }
    catch (DbEntityValidationException ex)
    {
        string errorMessages = string.Join("; ", ex.EntityValidationErrors.SelectMany(x => x.ValidationErrors).Select(x => x.ErrorMessage));
        throw new DbEntityValidationException(errorMessages);
    }
}

यह आपके संदर्भ की SaveChanges()विधि को अधिलेखित कर देगा और आपको सभी इकाई सत्यापन त्रुटियों वाली अल्पविराम से अलग सूची मिल जाएगी।

यह भी उत्पादन env में त्रुटियों को लॉग करने के लिए, केवल एक त्रुटि को फेंकने के बजाय सुधार कर सकता है।

आशा है कि यह उपयोगी है।


मुझे "DbContext Class" कहाँ मिल सकती है? मैं यह सब MVC सामान में नया हूँ। मैं एमवीसी 5 और एंटिटी फ्रेमवर्क का उपयोग कर रहा हूं। 6. मुझे नहीं पता कि मेरे समाधान एक्सप्लोरर में नाम क्या पसंद आएगा।
जस्टजॉन ऑक्ट

@JustJohn यह आपके डेटाबेस मॉडल (क्लास फ़ाइल) में है, यदि आपको नहीं पता कि यह वह जगह है जहाँ आप DbContextअपने प्रोजेक्ट के विरुद्ध कीवर्ड की पूरी खोज कर सकते हैं ।
चिट्टी मालेक

1
मुझे यह सबसे अच्छा लगता है क्योंकि यह ऐप में सार्वभौमिक समाधान है और यह बताता है कि सिस्टम में किसी भी अन्य मॉड्यूल के लिए बहुत बदलाव किए बिना सतह के नीचे क्या है
Korayem

3

यहाँ टोनी के विस्तार का विस्तार है ... :-)

एंटिटी फ्रेमवर्क 4.x के लिए, यदि आप मुख्य फ़ील्ड का नाम और मान प्राप्त करना चाहते हैं ताकि आपको पता चले कि किस संस्था के उदाहरण (DB रिकॉर्ड) में समस्या है, तो आप निम्न जोड़ सकते हैं। यह आपके DbContext ऑब्जेक्ट से अधिक शक्तिशाली ObjectContext वर्ग के सदस्यों तक पहुँच प्रदान करता है।

// Get the key field name & value.
// This assumes your DbContext object is "_context", and that it is a single part key.
var e = ((IObjectContextAdapter)_context).ObjectContext.ObjectStateManager.GetObjectStateEntry(validationErrors.Entry.Entity);
string key = e.EntityKey.EntityKeyValues[0].Key;
string val = e.EntityKey.EntityKeyValues[0].Value;

3

मैं अपवादों को पसंद नहीं करता हूं मैंने ऑनसेवचेंज को पंजीकृत किया है और यह मेरे पास है

var validationErrors = model.GetValidationErrors();

var h = validationErrors.SelectMany(x => x.ValidationErrors
                                          .Select(f => "Entity: " 
                                                      +(x.Entry.Entity) 
                                                      + " : " + f.PropertyName 
                                                      + "->" + f.ErrorMessage));

"मैंने OnSaveChanges पंजीकृत" कहने का क्या मतलब है?
अकीरा यामामोटो

मैं संदर्भ दूसरों के रूप में एक ही पर OnSaveChanges को झुका, मैं सिर्फ अपवाद स्तर तक पहुंच नहीं था \।
मिकी Perlstein

2

यह त्रुटि तब भी होती है जब आप एक ऐसी संस्था को बचाने की कोशिश करते हैं जिसमें सत्यापन त्रुटियां होती हैं। इसका एक अच्छा तरीका यह है कि आप अपने DB को बचाने से पहले ModelState.IsValid की जांच करना न भूलें।


2

सुनिश्चित करें कि यदि आपके पास DB पंक्ति में nvarchar (50) है तो आप इसमें 50characters डालने की कोशिश नहीं कर रहे हैं। बेवकूफ गलती लेकिन मुझे यह पता लगाने में 3 घंटे लगे।


1

यह किसी विशिष्ट स्तंभ के लिए अनुमत अधिकतम वर्णों के कारण हो सकता है, जैसे sql में एक फ़ील्ड में डेटा प्रकार निम्नलिखित हो सकता है, nvarchar(5)लेकिन उपयोगकर्ता से दर्ज किए गए वर्णों की संख्या निर्दिष्ट से अधिक है, इसलिए त्रुटि उत्पन्न होती है।


1

मैंने डेटाबेस को अपडेट करते समय कुछ दिनों पहले इसी मुद्दे का सामना किया है। मेरे मामले में, रखरखाव के लिए कुछ नए गैर-अशक्त कॉलम जोड़े गए थे जो कोड में आपूर्ति नहीं किए गए थे जो अपवाद का कारण बन रहा है। मैं उन क्षेत्रों का पता लगाता हूं और उनके और उसके समाधान के लिए मूल्यों की आपूर्ति करता हूं।


0

आपके जवाब के लिए थैंक्यू, यह मुझे एक बहुत मदद करते हैं। Vb.Net में i कोड के रूप में, Vb.Net के लिए यह बोल्ट कोड

Try
   Return MyBase.SaveChanges()
Catch dbEx As Validation.DbEntityValidationException
   For Each [error] In From validationErrors In dbEx.EntityValidationErrors
                       From validationError In validationErrors.ValidationErrors
                       Select New With { .PropertyName = validationError.PropertyName,
                                         .ErrorMessage = validationError.ErrorMessage,
                                         .ClassFullName = validationErrors.Entry.Entity
                                                                    .GetType().FullName}

        Diagnostics.Trace.TraceInformation("Class: {0}, Property: {1}, Error: {2}",
                                           [error].ClassFullName,
                                           [error].PropertyName,
                                           [error].ErrorMessage)
   Next
   Throw
End Try

0

यह प्रॉपर्टी के कारण हो सकता है जो मॉडल द्वारा पॉपुलेटेड नहीं है .. इसके बजाय यह कंट्रोलर द्वारा पॉपुलेटेड है .. जो इस त्रुटि का कारण हो सकता है .. इसका समाधान मॉडलस्टेट सत्यापन को लागू करने से पहले प्रॉपर्टी को असाइन करना है। और यह दूसरा अनुमान है आपके पास पहले से ही अपने डेटाबेस में डेटा हो सकता है और इसे अपडेट करने की कोशिश कर रहा है लेकिन अब इसे ला रहा है।


0

मेरे मामले में मेरे पास एक टेबल कॉलम नाम पथ है, जिसे मैंने सेटटाइप किया था, जो varchar (200) था। इसे nvarchar (अधिकतम) में अपडेट करने के बाद, मैंने edmx से तालिका को हटा दिया है और फिर तालिका को जोड़ा और यह मेरे लिए ठीक से जागा।

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