DbEntityValidationException - আমি কীভাবে সহজেই বলতে পারি কী কারণে ত্রুটি ঘটেছে?


217

আমার একটি প্রকল্প রয়েছে যা সত্তা ফ্রেমওয়ার্ক ব্যবহার করে। SaveChangesআমার কাছে ফোন করার সময় DbContext, আমি নিম্নলিখিত ব্যতিক্রমগুলি পেয়েছি:

সিস্টেম.ডাটা.এন্টিটি.বিলিডেশন.ডিবিএন্টিটি ভ্যালিডেশনএক্সসেপশন: এক বা একাধিক সত্তার জন্য বৈধকরণ ব্যর্থ হয়েছে। আরও তথ্যের জন্য 'সত্তাবিশেষকরণের ত্রুটি' সম্পত্তি দেখুন।

এটি সব ঠিকঠাক এবং ছিমছাম, তবে প্রতিবার এই ব্যতিক্রম ঘটলে আমি কোনও ডিবাগার সংযুক্ত করতে চাই না। আরও বেশি, উত্পাদন পরিবেশে আমি সহজেই কোনও ডিবাগার সংযুক্ত করতে পারি না তাই এই ত্রুটিগুলি পুনরুত্পাদন করতে আমাকে অনেকদূর যেতে হবে।

কীভাবে আমি এর মধ্যে লুকানো বিবরণ দেখতে পারি DbEntityValidationException?

উত্তর:


429

সবচেয়ে সহজ সমাধান হ'ল SaveChangesআপনার সত্তা শ্রেণিতে ওভাররাইড করা। আপনি ধরতে পারবেন DbEntityValidationException, প্রকৃত ত্রুটিগুলি মোড়ক DbEntityValidationExceptionকরে উন্নত বার্তাটি দিয়ে একটি নতুন তৈরি করতে পারেন ।

  1. আপনার সামথিংসোমথিং.কমটেক্সট.এস ফাইলের পাশের একটি আংশিক শ্রেণি তৈরি করুন।
  2. এই পোস্টের নীচে কোড ব্যবহার করুন।
  3. এটাই. আপনার বাস্তবায়ন স্বয়ংক্রিয়ভাবে কোনও রিফ্যাক্টর কাজ ছাড়াই ওভাররডিন সেভচেঞ্জগুলি ব্যবহার করবে।

আপনার ব্যতিক্রম বার্তা এখন এই মত দেখাচ্ছে:

সিস্টেম.ডাটা.এন্টিটি.বিলিডেশন.ডিবিএন্টিটি ভ্যালিডেশনএক্সসেপশন: এক বা একাধিক সত্তার জন্য বৈধকরণ ব্যর্থ হয়েছে। আরও তথ্যের জন্য 'সত্তাবিশেষকরণের ত্রুটি' সম্পত্তি দেখুন। বৈধতা ত্রুটিগুলি হ'ল: ক্ষেত্রের ফোন নাম্বার অবশ্যই '12' এর সর্বোচ্চ দৈর্ঘ্যের স্ট্রিং বা অ্যারের ধরণের হতে হবে; লাস্টনাম ফিল্ডটি প্রয়োজনীয়।

আপনি উত্তরাধিকার সূত্রে প্রাপ্ত কোনও শ্রেণিতে ওভাররাইড হওয়া সেভচেনজগুলি বাদ দিতে পারেন DbContext:

public partial class SomethingSomethingEntities
{
    public override int SaveChanges()
    {
        try
        {
            return base.SaveChanges();
        }
        catch (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);
    
            // Throw a new DbEntityValidationException with the improved exception message.
            throw new DbEntityValidationException(exceptionMessage, ex.EntityValidationErrors);
        }
    }
}

DbEntityValidationExceptionএছাড়াও সত্ত্বা যে বৈধতা ত্রুটি সৃষ্ট ধারণ করে। সুতরাং আপনার যদি আরও তথ্যের প্রয়োজন হয় তবে আপনি উপরোক্ত কোডটি এই সত্তাগুলি সম্পর্কে তথ্য আউটপুট পরিবর্তন করতে পারেন।

আরও দেখুন: http://devillers.nl/improving-dbentityvalidationexception/


6
উত্পন্ন উত্স শ্রেণীর বিভাগটি ইতিমধ্যে DbContext থেকে উত্তরাধিকার সূত্রে আসে যাতে আপনাকে এটি আবার আংশিক শ্রেণিতে যুক্ত করতে হবে না। আপনি আংশিক শ্রেণিতে যোগ করে কোনও কিছু ভাঙ্গবেন না বা পরিবর্তন করবেন না। প্রকৃতপক্ষে, আপনি ডিবি কনটেক্সট থেকে উত্তরাধিকার যুক্ত করলে, রিশার্পার আপনাকে এটি সরিয়ে দেওয়ার পরামর্শ দিবে: "বেস টাইপ 'ডিবি কনটেক্সট' ইতিমধ্যে অন্যান্য অংশে নির্দিষ্ট করা আছে।"
মার্টিন ডেভিলারস

15
কেন এটি সেভচেনজগুলির ডিফল্ট আচরণ নয়?
জন শেডলেটস্কি

4
"কেন এটি সেভচেনজের ডিফল্ট আচরণ নয়?" - এটা সত্যিই একটি ভাল প্রশ্ন. এটি একটি আশ্চর্যজনক সমাধান ছিল, এটি আমার ঘন্টা বাঁচিয়েছিল! আমাকে ফেলে দিতে হয়েছিলusing System.Linq;
জন

1
বেসে আমার তৈরি ত্রুটি তৈরি করুন ave সেভচেনজেস () যা চেষ্টা করার ব্লকটিতে রয়েছে। এটি কখনই ক্যাচ ব্লকে ঝাঁপ দেয় না। আমি আপনার কোডটি ওভার রাইড সেভচেনজেজে পেয়েছি তবে এটি ত্রুটি হয়ে কখনই ক্যাচ ব্লকে যায় না।
জাস্টজহান

7
স্ট্যাক ট্রেস সংরক্ষণ করার জন্য আপনার অভ্যন্তরীণ ব্যতিক্রমটি সেট করা উচিত।
dotjoe

48

মার্টিন ইঙ্গিত হিসাবে, আরও তথ্য আছে DbEntityValidationResult। আমি প্রতিটি বার্তায় আমার পোকো ক্লাসের নাম এবং সম্পত্তির নাম উভয়ই পেতে দরকারী বলে খুঁজে পেয়েছি এবং কেবলমাত্র এই জন্য ErrorMessageআমার সমস্ত [Required]ট্যাগগুলিতে কাস্টম বৈশিষ্ট্যগুলি লিখতে হবে না ।

মার্টিনের কোডে নিম্নলিখিত টুইটগুলি আমার জন্য এই বিবরণগুলির যত্ন নিয়েছিল:

// Retrieve the error messages as a list of strings.
List<string> errorMessages = new List<string>();
foreach (DbEntityValidationResult validationResult in ex.EntityValidationErrors)
{
    string entityName = validationResult.Entry.Entity.GetType().Name;
    foreach (DbValidationError error in validationResult.ValidationErrors)
    {
        errorMessages.Add(entityName + "." + error.PropertyName + ": " + error.ErrorMessage);
    }
}

1
ব্যবহার SelectMany and Aggregateমধ্যে GitHub দ্বারা সাহসী পরিকল্পনাটি
Kiquenet

43

EntityValidationErrorsসংগ্রহটি দেখতে , ওয়াচ উইন্ডোতে নিম্নলিখিত ওয়াচ এক্সপ্রেশনটি যুক্ত করুন।

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

আমি ভিজ্যুয়াল স্টুডিও 2013 ব্যবহার করছি


$ ব্যতিক্রম উজ্জ্বল! এর অর্থ হ'ল তাত্ক্ষণিক উইন্ডোতে আমি; ব্যতিক্রম করতে পারি ntঅন্টিটিভিডিলেশনআরিয়ার্স S নির্বাচন করুন (x => x.VوادationErferences) S নির্বাচন করুন (x => x.ErrorMessage);
chrispepper1989

13

আপনি মধ্যে ডিবাগ মোডে হলেও catch {...}ব্লক "QuickWatch" উইন্ডো খুলুন ( ctrl+ + alt+ + q) এবং সেখানে আটকান:

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

এটি আপনাকে ValidationErrorsগাছের মধ্যে ড্রিল করতে দেয় । এই ত্রুটিগুলির মধ্যে তাত্ক্ষণিক অন্তর্দৃষ্টি পাওয়া এটি সবচেয়ে সহজ উপায়।

ভিজ্যুয়াল ২০১২++ ব্যবহারকারীদের জন্য যারা কেবল প্রথম ত্রুটিটি সম্পর্কে চিন্তা করেন এবং তাদের কোনও catchব্লক নাও থাকতে পারে , আপনি এমনকি এটি করতে পারেন:

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

9

ডিবাগিংয়ের সময় ত্রুটিটি পরীক্ষা করে দ্রুত অর্থবহ ত্রুটি বার্তা সন্ধান করতে:

  • এর জন্য একটি দ্রুত ঘড়ি যুক্ত করুন:

    ((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors
  • সত্তাবিহীনকরণের মতো ত্রুটিগুলি এখানে ড্রিল করুন:

    (সংগ্রহ আইটেম যেমন [0])> বৈধতা ত্রুটিগুলি> (সংগ্রহ আইটেম যেমন [0])> ত্রুটিমাখা


5

প্রকৃতপক্ষে, এটি কেবল বৈধকরণের ইস্যু, EF ডাটাবেসে কোনও পরিবর্তন আনার আগে সত্তার বৈশিষ্ট্যগুলিকে প্রথমে বৈধতা দেবে। সুতরাং, EF আপনার সারণীটি নকশা করার সময় যেমন সম্পত্তিটির মূল্য সীমার বাইরে রয়েছে কিনা তা পরীক্ষা করবে। টেবিল_কলাম_ইউজারনেমটি ভারচার (20)। তবে, ইএফ-তে আপনি এমন একটি মান সন্নিবেশ করেছেন যা 20 এর চেয়ে দীর্ঘ। অথবা, অন্য ক্ষেত্রে, যদি কলামটি নাল হতে দেয় না। সুতরাং, বৈধতা প্রক্রিয়াতে, আপনাকে নাল কলামের জন্য একটি মান নির্ধারণ করতে হবে, আপনি এটি পরিবর্তন করছেন কিনা তা বিবেচনা করুন। আমি ব্যক্তিগতভাবে লেনিয়েল ম্যাকাফেরির উত্তরটির মতো। এটি আপনাকে বৈধতা সংক্রান্ত সমস্যার বিস্তারিত প্রদর্শন করতে পারে


4

আমি মনে করি "প্রকৃত বৈধতা ত্রুটিগুলি" সংবেদনশীল তথ্য থাকতে পারে এবং মাইক্রোসফ্ট তাদের অন্য জায়গায় (সম্পত্তি) রাখার জন্য এই কারণ হতে পারে। এখানে চিহ্নিত সমাধানটি ব্যবহারিক, তবে এটি সাবধানতার সাথে নেওয়া উচিত।

আমি একটি এক্সটেনশন পদ্ধতি তৈরি করতে পছন্দ করব। এর আরও কারণ:

  • মূল স্ট্যাক ট্রেস রাখুন
  • উন্মুক্ত / বদ্ধ নীতি অনুসরণ করুন (যেমন: আমি বিভিন্ন ধরণের লগের জন্য বিভিন্ন বার্তা ব্যবহার করতে পারি)
  • উত্পাদনের পরিবেশে অন্যান্য স্থান (যেমন: অন্যান্য dbcontext) থাকতে পারে যেখানে একটি DbEntityValidationException নিক্ষেপ করা যেতে পারে।

1

অ্যাজুরে ফাংশনগুলির জন্য আমরা মাইক্রোসফ্ট.এক্সটেনশনগুলি.লগিং.আইলোগারে এই সাধারণ বর্ধনটি ব্যবহার করি

public static class LoggerExtensions
{
    public static void Error(this ILogger logger, string message, Exception exception)
    {
        if (exception is DbEntityValidationException dbException)
        {
            message += "\nValidation Errors: ";
            foreach (var error in dbException.EntityValidationErrors.SelectMany(entity => entity.ValidationErrors))
            {
                message += $"\n * Field name: {error.PropertyName}, Error message: {error.ErrorMessage}";
            }
        }

        logger.LogError(default(EventId), exception, message);
    }
}

এবং ব্যবহারের উদাহরণ:

try
{
    do something with request and EF
}
catch (Exception e)
{
    log.Error($"Failed to create customer due to an exception: {e.Message}", e);
    return await StringResponseUtil.CreateResponse(HttpStatusCode.InternalServerError, e.Message);
}

0

আপনার কোডটিতে ট্রাই ব্লক ব্যবহার করুন

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

আপনি এখানে বিশদ পরীক্ষা করতে পারেন

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

  2. এক বা একাধিক সত্তার জন্য বৈধতা ব্যর্থ হয়েছে। আরও তথ্যের জন্য 'সত্তাবিশেষকরণের ত্রুটি' সম্পত্তি দেখুন

  3. http://blogs.infosupport.com/improving-dbentityvalidationexception/


আপনার তৃতীয় লিঙ্কটি গৃহীত উত্তরের ব্লগের অনুলিপি, তবে অন্য কোনও সাইটে। দ্বিতীয় লিঙ্কটি একটি স্ট্যাক ওভারফ্লো প্রশ্ন যা ইতিমধ্যে আপনার প্রথম লিঙ্কটি উল্লেখ করে re
এরিস

সুতরাং, যথাযথ রেফারেন্স সহ কাউকে সাহায্য করার চেষ্টা করা এখানে কোনও সমস্যা?
আতা এইচ।

হ্যাঁ, আপনার উত্তরে কেবল লিঙ্ক থাকা উচিত নয়। একটি সংক্ষিপ্তসার তৈরি করুন যা প্রশ্নের উত্তর দেয় এবং তারপরে আরও পড়ার জন্য লিঙ্কটি শেষে পোস্ট করুন।
ক্রিসও
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.