c# - شرح - insert update delete in mvc 4 using entity framework




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

أرغب في حفظ تعديلي إلى قاعدة البيانات وأنا أستخدم كود 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" لمزيد من التفاصيل.]


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

أعتقد أن إضافة المحاولة / الالتقاط لكل عملية 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 الإنتاج ، بدلاً من مجرد رمي خطأ.

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


تأكد من أنه إذا كان لديك nvarchar (50) في صف DB فأنت لا تحاول إدخال أكثر من 50 حرفًا في ذلك. خطأ غبي لكنه أخذني 3 ساعات لأكتشفه.


ساعد هذا الرمز في العثور على مشكلتي عندما واجهت مشكلة مع Erg VAlidation Erros. أخبرني المشكلة بالضبط مع تعريف الكيان الخاص بي. حاول اتباع التعليمات البرمجية حيث تحتاج إلى تغطية storeDB.SaveChanges ()؛ في ما يلي بعد محاولة كتلة الصيد.

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

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


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


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

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


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


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

بالنسبة لـ 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;

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


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

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

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

أو:

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

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

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





code-first