EF कोड पहले: मैं कैसे 'EntityValidationErrors' को नगेट पैकेज कंसोल से देख सकता हूँ?


127

मैं इसके लिए नुकसान में हूं:

मैंने एक इकाई रूपरेखा (4.1.3) कोड के लिए अपनी कक्षाओं को पहले दृष्टिकोण से परिभाषित किया है। सब कुछ ठीक था (मैं तालिकाओं आदि का निर्माण कर रहा था) जब तक मैंने बीज लेना शुरू नहीं किया।

अब जब मैं करता हूँ

Add-Migration "remigrate" ; Update-Database;

मुझे पैकेज कंसोल पर एक त्रुटि मिलती है "सत्यापन एक या अधिक संस्थाओं के लिए विफल रहा। अधिक विवरण के लिए 'EntityValidationErrors' संपत्ति देखें।"

मेरी सीड () विधि में एक ब्रेकपॉइंट है, लेकिन क्योंकि मैं कंसोल पर चल रहा हूं, जब प्रोजेक्ट नहीं चल रहा है, मैं विवरण के लिए कैसे प्राप्त कर रहा हूं, (PS - मैंने देखा है कि थ्रेड सत्यापन विफल हो गया है एंटिटी फ्रेमवर्क का उपयोग करते हुए SQL सर्वर डेटाबेस में परिवर्तन को सहेजते समय एक या एक से अधिक संस्थाओं के लिए जो दिखाता है कि मैं संपत्ति कैसे देख सकता हूं।)

मुझे पता है कि मेरे सीड () विधि में समस्या है क्योंकि अगर मैं विधि कॉल के ठीक बाद रिटर्न देता हूं, तो त्रुटि दूर हो जाती है। तो मैं अपना ब्रेकपॉइंट कैसे सेट करूं ताकि मैं देख सकूं कि सत्यापन त्रुटि क्या है? किंडा हार गया। या वहाँ किसी अन्य तरीके से इसे nuget कंसोल में ट्रेस किया जाता है ??


त्वरित अद्यतन: मैंने अपनी समस्या को व्यवस्थित रूप से अपनी विधि के भीतर तब तक ट्रैक करके अपनी समस्या को हल किया जब तक कि मैंने यह नहीं पाया कि त्रुटि क्या थी। हालाँकि, मैं अभी भी अपने प्रश्न का उत्तर जानना चाहूंगा क्योंकि यह बहुत तेज़ होगा!
जेरेमी

मुझे लगता है कि आप माइग्रेशन को प्रोग्रामेटिक रूप से चला सकते हैं और फिर त्रुटियों पर अपवाद और पुनरावृति पकड़ सकते हैं। यह आदर्श नहीं है लेकिन आपको आवश्यक विवरण दे सकता है।
पावेल

जब गलत उत्तर उत्तरों के शीर्ष पर होता है तो निराशा होती है और सारा श्रेय उसे मिल जाता है। एक ऐसी जगह जहां स्टैकऑवरफ्लो स्पष्ट रूप से कम हो जाता है!
jwize

यदि आप एंटिटी फ्रेमवर्क का उपयोग करते हैं, तो आप समाधान पर मेरे जवाब पर एक नज़र डाल सकते हैं "सत्यापन एक या एक से अधिक संस्थाओं के लिए विफल। अधिक विवरण के लिए 'EntityValidationErrors' संपत्ति देखें । आशा है कि यह मदद करता है ...
Murat Yıldız

जवाबों:


216

मुझे इससे हाल ही में गुस्सा भी आया। मैंने बीज विधि में विन्यास वर्ग में एक आवरण समारोह लगाकर इसे ठीक कर दिया, और SaveChangesइसके बजाय कॉल को मेरे कार्य के साथ बदल दिया । इस समारोह में बस त्रुटियों को दूर करना होगाEntityValidationErrors संग्रह के , और अपवाद अपवाद को हटा देगा जहां अपवाद संदेश व्यक्तिगत समस्याओं को सूचीबद्ध करता है। यह NuGet पैकेज मैनेजर कंसोल में आउटपुट दिखाता है।

कोड निम्नानुसार है:

/// <summary>
/// Wrapper for SaveChanges adding the Validation Messages to the generated exception
/// </summary>
/// <param name="context">The context.</param>
private void SaveChanges(DbContext context) {
    try {
        context.SaveChanges();
    } catch (DbEntityValidationException ex) {
        StringBuilder sb = new StringBuilder();

        foreach (var failure in ex.EntityValidationErrors) {
            sb.AppendFormat("{0} failed validation\n", failure.Entry.Entity.GetType());
            foreach (var error in failure.ValidationErrors) {
                sb.AppendFormat("- {0} : {1}", error.PropertyName, error.ErrorMessage);
                sb.AppendLine();
            }
        }

        throw new DbEntityValidationException(
            "Entity Validation Failed - errors follow:\n" + 
            sb.ToString(), ex
        ); // Add the original exception as the innerException
    }
}

बस अपने बीज विधि में कॉल के context.SaveChanges()साथ बदलें SaveChanges(context)


रिचर्ड, आखिर! किसी विचार के साथ। एक बार कोशिश करने के बाद मैं इस सवाल पर वापस आऊंगा।
जेरेमी

यह वास्तव में नास्टियों पर नज़र रखने में मदद करता है :)
एमिनेम

3
मैंने इस तकनीक का उपयोग किया, लेकिन संदर्भ के बजाय savechanges के एक ओवरराइड का उपयोग किया। public override int SaveChanges() संदर्भ के अंदर।
कर्स्टन लालच

5
आंशिक कक्षाओं का उपयोग करना अधिक प्रभावी है जैसा कि मैंने नीचे उत्तर दिया है।
jwize

1
यदि आप अपने बीज विधि में उपयोगकर्ता प्रबंधन कर रहे हैं, तो इस परिवर्तन में आउटपुट में सत्यापन त्रुटियाँ शामिल नहीं होंगी, आपको @jwize उत्तर के अनुसार DBContext SaveChanges, SaveChangesAsync और SaveChangesAsync (CT) विधियों को ओवरराइड करना होगा।
कार्ल

115

एक आंशिक वर्ग परिभाषा के साथ पहले से ही अपने DBContext क्लास बढ़ाएँ!

यदि आप अपने DbContext के लिए वर्ग परिभाषा को देखते हैं तो यह निम्नलिखित की तरह होगा:

// DatabaseContext.cs   -- This file is auto generated and thus shouldn't be changed. 
public partial class [DatabaseContextName] : DbContext { ... }

इसलिए, एक अन्य फ़ाइल में आप एक ही परिभाषा बना सकते हैं और उन हिस्सों को ओवरराइड कर सकते हैं जिन्हें आप चाहते हैं।

// partialDatabaseContext.cs  -- you can safely make changes 
// that will not be overwritten in here.
public partial class [DatabaseContextName] : DbContext { // Override defaults here } 

आंशिक वर्गों के साथ पूरे विचार तुम नोटिस --did DbContext एक आंशिक class-- है कि आप एक वर्ग है कि तैयार की गई है का विस्तार (या अधिक फ़ाइलों में कक्षाओं का आयोजन) कर सकते हैं और हमारे मामले में हम भी चाहते हैं ओवरराइड SaveChanges विधि एक आंशिक वर्ग के भीतर से जो DbContext में जोड़ता है ।

इस तरह हम सभी मौजूदा DbContext / SaveChanges कॉल से त्रुटि डिबगिंग जानकारी प्राप्त कर सकते हैं और आपको अपना बीज कोड या विकास कोड बिल्कुल भी नहीं बदलना होगा।

यह मैं क्या करूँगा ( ध्यान दें अंतर यह है कि मैं अपने स्वयं के लेखक DbContext आंशिक वर्ग में, केवल सामान्य नहीं है ) में SaveChanges विधि को ओवरराइड करता हूं । इसके अलावा, सुनिश्चित करें कि आप आंशिक वर्ग सही नामस्थान का उपयोग करते हैं या आप दीवार के खिलाफ अपना सिर पीट रहे होंगे।

public partial class Database : DbContext
{
    public override int SaveChanges()
    {
        try
        {
            return base.SaveChanges();
        }
        catch (DbEntityValidationException ex)
        {
            var sb = new StringBuilder();

            foreach (var failure in ex.EntityValidationErrors)
            {
                sb.AppendFormat("{0} failed validation\n", failure.Entry.Entity.GetType());
                foreach (var error in failure.ValidationErrors)
                {
                    sb.AppendFormat("- {0} : {1}", error.PropertyName, error.ErrorMessage);
                    sb.AppendLine();
                }
            }

            throw new DbEntityValidationException(
                "Entity Validation Failed - errors follow:\n" +
                sb.ToString(), ex
                ); // Add the original exception as the innerException
        }
    }
}

आप एक प्रतिभाशाली हैं ...!
फ्लोरियन एफ।

महान समाधान। लोगों को उत्थान करने से पहले सभी उत्तरों को पढ़ना चाहिए।
गिलहर्मे डे जीसस सैंटोस

3
आपको SaveChangesAsync और SaveChangesAsync (CancellationToken) को भी ओवरराइड करना चाहिए - कम से कम यही बात पहले कोड के साथ होती है, पहले मॉडल / डीबी के बारे में निश्चित नहीं।
कार्ल

@jwize। आपके उत्तर ने मुझे मेरे डेटाबेस में पहले मॉडलिंग अपवाद मुद्दों से निपटने में मदद की। महान जवाब
3355307

1
CodeFirst का उपयोग करते समय DbContext स्पष्ट रूप से उत्पन्न नहीं होता है। हालाँकि, जब आप डिज़ाइनर का उपयोग करते हैं तो DbContext और Entity कक्षाएं उत्पन्न होती हैं और उन्हें आंशिक वर्ग का उपयोग करके ओवरराइड किया जाना चाहिए।
jwize

35

मैंने रिचर्ड्स को एक विस्तार विधि में उत्तर दिया:

  public static int SaveChangesWithErrors(this DbContext context)
    {
        try
        {
            return context.SaveChanges();
        }
        catch (DbEntityValidationException ex)
        {
            StringBuilder sb = new StringBuilder();

            foreach (var failure in ex.EntityValidationErrors)
            {
                sb.AppendFormat("{0} failed validation\n", failure.Entry.Entity.GetType());
                foreach (var error in failure.ValidationErrors)
                {
                    sb.AppendFormat("- {0} : {1}", error.PropertyName, error.ErrorMessage);
                    sb.AppendLine();
                }
            }

            throw new DbEntityValidationException(
                "Entity Validation Failed - errors follow:\n" +
                sb.ToString(), ex
            ); // Add the original exception as the innerException
        }
    }

इस तरह से कॉल करें:

context.SaveChangesWithErrors();

4

मैंने क्रेगेल के संस्करण को C # में परिवर्तित किया था, मुझे संदर्भ जोड़ना था ।aveChanges (); नीचे के रूप में यह मेरे लिए काम करने के लिए।

try
{
    byte[] bytes = System.IO.File.ReadAllBytes(@"C:\Users\sheph_000\Desktop\Rawr.png");
    Console.WriteLine(bytes);

    context.BeverageTypes.AddOrUpdate(
        x => x.Name,
        new AATPos.DAL.Entities.BeverageType { ID = 1, Name = "Sodas" }
        );

    context.Beverages.AddOrUpdate(
        x => x.Name,
        new AATPos.DAL.Entities.Beverage { ID = 1, Name = "Coke", BeverageTypeID = 1, ImageData = bytes, IsStocked = true, StockLevel = 10, Price = 10.00M, ImageMimeType = "test" },
        new AATPos.DAL.Entities.Beverage { ID = 2, Name = "Fanta", BeverageTypeID = 1, ImageData = bytes, IsStocked = true, StockLevel = 10, Price = 10.00M, ImageMimeType = "test" },
        new AATPos.DAL.Entities.Beverage { ID = 3, Name = "Sprite", BeverageTypeID = 1, ImageData = bytes, IsStocked = true, StockLevel = 10, Price = 10.00M, ImageMimeType = "test" },
        new AATPos.DAL.Entities.Beverage { ID = 4, Name = "Cream Soda", BeverageTypeID = 1, ImageData = bytes, IsStocked = true, StockLevel = 10, Price = 10.00M, ImageMimeType = "test" },
        new AATPos.DAL.Entities.Beverage { ID = 5, Name = "Pepsi", BeverageTypeID = 1, ImageData = bytes, IsStocked = true, StockLevel = 10, Price = 10.00M, ImageMimeType = "test" }
        );

    context.SaveChanges();
}
catch (System.Data.Entity.Validation.DbEntityValidationException ex)
{
    var sb = new System.Text.StringBuilder();
    foreach (var failure in ex.EntityValidationErrors)
            {
                sb.AppendFormat("{0} failed validation", failure.Entry.Entity.GetType());
        foreach (var error in failure.ValidationErrors)
                {
            sb.AppendFormat("- {0} : {1}", error.PropertyName, error.ErrorMessage);
            sb.AppendLine();
                }
            }

    throw new Exception(sb.ToString());
}

3

रिचर्ड ने मुझे सही रास्ते पर लाने के लिए धन्यवाद (उसी मुद्दे पर) नीचे दिए गए आवरण के बिना एक विकल्प है जो मेरे लिए माइग्रेशन के बीज बीज में काम करता है:

 Protected Overrides Sub Seed(context As NotificationContext)

        Try
            context.System.AddOrUpdate(
               Function(c) c.SystemName,
                New E_NotificationSystem() With {.SystemName = "System1"},
                New E_NotificationSystem() With {.SystemName = "System2"},
                New E_NotificationSystem() With {.SystemName = "System3"})

            context.SaveChanges()

        Catch ex As DbEntityValidationException

            Dim sb As New StringBuilder

            For Each failure In ex.EntityValidationErrors

                sb.AppendFormat("{0} failed validation" & vbLf, failure.Entry.Entity.[GetType]())

                For Each [error] In failure.ValidationErrors
                    sb.AppendFormat("- {0} : {1}", [error].PropertyName, [error].ErrorMessage)
                    sb.AppendLine()
                Next
            Next

            Throw New Exception(sb.ToString())

        End Try
End Sub

तब पैकेज मैनेजर कंसोल में अपवाद देखने में सक्षम था। आशा है कि यह किसी की मदद करता है।


-1

I Also had same model validation problem but successfully catch by myself after lot of thinking;

I use reverse engineering method to catch the problem out of Over 80 + Model Classes;

1> Made copy of dbcontext, changing the name (I add "1" at end and make respective changes in class constructor and initialization etc.

Old:
 
>public class AppDb : IdentityDbContext<ApplicationUser>
>     
> {
> public AppDb(): base("DefaultConnection", throwIfV1Schema: false)
> {
> 
> }
>     
> public static AppDb Create()
>{
>return new AppDb();
>} 

**New:**

>public class AppDb1 : IdentityDbContext<ApplicationUser>
>{
>public AppDb1()
>: base("DefaultConnection", throwIfV1Schema: false)
>{
>}
> 
>public static AppDb1 Create()
> {
> return new AppDb1();
>  }`

...
2> Make changes to Codefirst Migration Configuration from Old DbContext to my new Context.

> internal sealed class Configuration :
> DbMigrationsConfiguration<DAL.AppDb1> { public Configuration() {
> AutomaticMigrationsEnabled = false; }    protected override void
> Seed(DAL.AppDb1 context) {`

3> Comment the Dbsets in new DbContext which was doubt.
4> Apply update migration if succeeded the probelm lye in Commented section.
5> if not then commented section is clear of bug clear.
6> repeat the (4) until found the right place of bug.
7> Happy Codding


1
अच्छा होगा जब आप अपने कोड को प्रारूपित करेंगे कि आपका पाठ एक कोड ब्लॉक के अंदर नहीं है।
जम्मूतवीस

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