c# شرح - فشل التحقق من الصحة لواحد أو أكثر من الكيانات أثناء حفظ التغييرات في قاعدة بيانات خادم SQL باستخدام Entity Framework




tutorial source (14)

قد يكون هذا بسبب الحد الأقصى لعدد الأحرف المسموح بها لعمود معين ، كما هو الحال في sql ، قد يكون حقل واحد يتبع نوع البيانات nvarchar(5) ولكن عدد الأحرف التي تم إدخالها من المستخدم أكبر من العدد المحدد ، وبالتالي يظهر الخطأ.

أرغب في حفظ تعديلي إلى قاعدة البيانات وأنا أستخدم كود Entity FrameWork الأول في ASP.NET MVC 3 / C # ولكنني أواجه أخطاء. في فئة الحدث الخاص بي ، لدي أنواع البيانات DateTime و TimeSpan ولكن في قاعدة البيانات الخاصة بي ، لقد حصلت على التاريخ والوقت على التوالي. يمكن أن يكون هذا هو السبب؟ كيف يمكنني الإرسال إلى نوع البيانات المناسب في التعليمة البرمجية قبل حفظ التغييرات في قاعدة البيانات.

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.SaveChanges ()؛

// 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 Database / T-SQL

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

شكل المتشعب

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" لمزيد من التفاصيل.]


كتحسين لكل من برافين وتوني ، استخدم تجاوزًا:

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

لقد واجهت نفس المشكلة قبل بضعة أيام أثناء تحديث قاعدة البيانات. في حالتي ، كان هناك عدد قليل من الأعمدة الجديدة غير القابلة للإضافة التي تمت إضافتها للصيانة والتي لم يتم توفيرها في التعليمة البرمجية التي تتسبب في الاستثناء. أجد تلك الحقول وأمدنا بها بالقيم وحللتها.


يمكنك استخراج كافة المعلومات من 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);
        }
    }
}

يحدث هذا الخطأ أيضًا عند محاولة حفظ كيان يحتوي على أخطاء في التحقق من الصحة. طريقة جيدة للتسبب في ذلك هي نسيان التحقق من ModelState.IsValid قبل الحفظ إلى قاعدة بياناتك.


Thnaks لإجاباتك ، فإنه يساعدني كثيرا. كما أنا كود في Vb.Net ، وهذا رمز بولت ل 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

قد يحدث ذلك بسبب الخاصية التي لا يتم نشرها بالنموذج .. بدلاً من ذلك يتم ملؤها بواسطة وحدة التحكم .. والتي قد تتسبب في حدوث هذا الخطأ. حل هذا هو تعيين الخاصية قبل تطبيق التحقق من صحة ModelState. وهذا الافتراض الثاني هو. قد يكون لديك بالفعل بيانات في قاعدة البيانات الخاصة بك ومحاولة تحديثها ولكن الآن في جلبها.


وهنا امتداد لتمديد طوني ... :-)

بالنسبة لـ Entity Framework 4.x ، إذا كنت ترغب في الحصول على اسم حقل المفتاح وقيمته حتى تعرف أي مثيل للكيان (سجل DB) لديه المشكلة ، يمكنك إضافة ما يلي. يوفر هذا الوصول إلى أعضاء فئة ObjectContext أكثر فعالية من كائن DbContext الخاص بك.

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

أعتقد أن إضافة المحاولة / الالتقاط لكل عملية 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() الخاصة SaveChanges() وستحصل على قائمة مفصولة بفواصل تحتوي على جميع أخطاء التحقق من الكيانات.

هذا أيضا يمكن أن تتحسن ، لتسجيل الأخطاء في env الإنتاج ، بدلاً من مجرد رمي خطأ.

أتمنى أن يكون هذا مفيدًا.


لا تغيير الرمز المطلوب:

أثناء وجودك في وضع التصحيح داخل كتلة catch {...} افتح النافذة "QuickWatch" ( Ctrl + Alt + Q ) والصق هناك:

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

أو:

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

إذا لم تكن في تجربة / تجربة أو لم يكن لديك حق الوصول إلى كائن الاستثناء.

سيسمح لك هذا ValidationErrors شجرة ValidationErrors . إنها الطريقة الأسهل التي وجدتها للحصول على إحصاءات فورية عن هذه الأخطاء.


كنت أتلقى هذا الخطأ اليوم ولم أستطع استخدامه لبعض الوقت ، لكنني أدركت أنه كان بعد إضافة بعض RequireAttribute إلى RequireAttribute وأن بعض بيانات بذور التنمية لم تكن تملأ جميع الحقول المطلوبة.
إذن مجرد ملاحظة أنه إذا كنت تحصل على هذا الخطأ أثناء تحديث قاعدة البيانات من خلال نوع من استراتيجية DropCreateDatabaseIfModelChanges مثل DropCreateDatabaseIfModelChanges فيجب عليك التأكد من أن بيانات البذور الخاصة بك تلبي وتفي بأي خصائص التحقق من صحة بيانات النموذج .

أعلم أن هذا يختلف قليلاً عن المشكلة في السؤال ، ولكنه سؤال شائع لذلك أعتقد أني سأضيف أكثر قليلاً إلى الإجابة للآخرين الذين لديهم نفس المشكلة مثلي.
آمل أن يساعد هذا :) :)


أنا لا أحب الاستثناءات سجلت OnSaveChanges ولدي هذا

var validationErrors = model.GetValidationErrors();

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

في حالة وجود فصول دراسية بأسماء المواقع نفسها ، فإليك امتدادًا صغيرًا لجواب برافين:

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

BrightstarDB من Codeplex. BrightstarDB هو قاعدة بيانات NoSQL مفتوحة المصدر وسريعة ويمكن تضمينها وقابلة للتوسعة لمنصة دوت نت مع إنشاء نموذج للبيانات البرمجية الأولى.





c# sql asp.net-mvc entity-framework code-first