سؤال

لدي السيناريو التالي:

  1. الكيانات التي يتم تحميلها من قاعدة البيانات.
  2. واحد منهم هو تقديم للمستخدم في شكل (WPF UserControl) حيث يمكن للمستخدم تحرير خصائص هذا الكيان.
  3. يمكن للمستخدم أن يقرر تطبيق التغييرات إلى الكيان أو إلغاء التحرير.

كيف يمكنني تنفيذ شيء مثل هذا مع EntityFramework?

مشكلتي هي أنني عندما ربط واجهة المستخدم مباشرة إلى خصائص كيان كل تغيير هو instantanously تطبيقها على الكيان.أريد أن تأخير ذلك إلى اللحظة التي يكون فيها المستخدم بالضغط على موافق و الكيان يتم التحقق من صحة بنجاح.

فكرت تحميل الكيانات NoTracking و الدعوة ApplyPropertyChanges بعد فصل كيان تم التحقق من صحة, ولكن أنا لست متأكدا تماما عن الطريقة الصحيحة للقيام بذلك.Docu من EntityFramework في MSDN هو متفرق جدا.

طريقة أخرى كنت أفكر فيه هو أن Refresh الكيان StoreWins, ولكن أنا لا أحب إعادة تعيين التغييرات في إلغاء بدلا من تطبيق التغييرات على موافق.

وقد أي شخص من أي برنامج تعليمي جيد أو العينة ؟

هل كانت مفيدة؟

المحلول

أحد الخيارات هو ما قلت لا لا تتبع الاستعلام.

ctx.Customers.MergeOption = MergeOption.NoTracking;
var customer = ctx.Customers.First(c => c.ID == 232);

ثم يمكن للعميل تعديل 'customer' كما هو مطلوب في الذاكرة و لا شيء يحدث في الواقع في سياق.

الآن عندما تريد في الواقع جعل التغيير يمكنك أن تفعل هذا:

// get the value from the database
var original = ctx.Customers.First(c => c.ID == customer.ID);
// copy values from the changed entity onto the original.
ctx.ApplyPropertyChanges(customer); .
ctx.SaveChanges();

الآن إذا كنت غير مريح مع الاستعلام إما الأداء أو التزامن الأسباب ، يمكنك إضافة ملحق جديد طريقة AttachAsModified(...) إلى ObjectContext.

التي تبدو شيئا مثل هذا:

public static void AttachAsModified<T>(
    this ObjectContext ctx, 
    string entitySet, 
    T entity)
{
    ctx.AttachTo(entitySet, entity);

    ObjectStateEntry entry = 
            ctx.ObjectStateManager.GetObjectStateEntry(entity);

    // get all the property names
    var propertyNames = 
            from s in entry.CurrentValues.DataRecordInfo.FieldMetadata
            select s.FieldType.Name;

    // mark every property as modified    
    foreach(var propertyName in propertyNames)
    {
        entry.SetModifiedProperty(propertyName);
    }
}

الآن يمكنك كتابة رمز مثل هذا:

ctx.Customers.MergeOption = MergeOption.NoTracking;
var customer = ctx.Customers.First();
// make changes to the customer in the form
ctx.AttachAsModified("Customers", customer);
ctx.SaveChanges();

والآن لا يوجد لديك التزامن أو extranous الاستعلامات.

المشكلة الوحيدة الآن هو التعامل مع FK خصائص.ربما يجب أن ننظر في بلدي مؤشر نصائح للحصول على المساعدة هنا: http://blogs.msdn.com/alexj/archive/2009/03/26/index-of-tips.aspx

ويساعد هذا الأمل

اليكس

نصائح أخرى

أقترح IEditableObject أيضا بالإضافة إلى ذلك IDataErrorInfo.

طريقتي في ذلك هو أنني في الأساس viewmodel على الكيان أن يأخذ الكيان منشئ المعلمة (في الأساس كائن المجمع).

في BeginEdit عندي نسخة الكيان خصائص بلدي viewmodel ، حتى لو كنت تفعل CancelEdit البيانات هو فقط تغيير في ViewModel و الكيان الأصلي لم يتغير.في EndEdit, أنا مجرد تطبيق ViewModel خصائص الكيان مرة أخرى ، أو بالطبع إلا إذا كان التحقق من صحة نجحت.

من أجل التحقق من صحة استخدام أساليب IDataErrorInfo.أنا فقط تنفيذ IDataErrorInfo.خطأ بحيث يتحقق كل اسم الخاصية عبر IDataErrorInfo[سلسلة columnName] و يسلسل في نهاية المطاف رسائل الخطأ.إذا كان فارغا, كل شيء على ما يرام.(لست متأكدا إذا كان الخطأ المفترض أن تستخدم هذه الطريقة ولكن لا تفعل ذلك)

إذا كان لدى الكيانات الأخرى المرفقة إلى بلدي الأصلي الكيان ، مثل العملاء.أوامر إنشاء لهم كما متداخلة ViewModels في الأصل كيان ViewModel.الأصلي ViewModel المكالمات انها بوصة' تبدأ-إلغاء-,EndEdit / خطأ الأساليب في نفسه تطبيقات من تلك الطرق.

انها أكثر قليلا من العمل ، ولكن أعتقد أنه يستحق ذلك لأن بين BeginEdit و EndEdit, يمكنك أن تكون متأكد من أن لا شيء يتغير دون أن يلاحظ ذلك.وجود مقتطف شفرة INotifyPropertyChanged تمكين خصائص يساعد كثيرا أيضا.

العادي طريقة للقيام بذلك هو ملزم بشيء تنفذ IEditableObject.إذا ومدى تناسبها مع الكيان الإطار ، أنا لست متأكدا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top