نمط البيانات الأساسية: كيفية تحديث المعلومات المحلية بكفاءة مع التغييرات من الشبكة؟

StackOverflow https://stackoverflow.com/questions/2209228

سؤال

لدي بعض عدم الكفاءة في تطبيقي الذي أود فهمه وإصلاحه.

خوارزمي هي:

fetch object collection from network
for each object:
  if (corresponding locally stored object not found): -- A
    create object
    if (a nested related object locally not found): -- B
      create a related object

أقوم بفحص الخطوط A و B عن طريق إنشاء استعلام مسند مع مفتاح الكائنات ذات الصلة جزءا من مخططي. أرى أن كل من (دائما) و b (إذا تم التنفيذ المتفرع في هذا الجزء) إنشاء SQL حدد مثل:

2010-02-05 01:57:51.092 app[393:207] CoreData: sql: SELECT <a bunch of fields> FROM ZTABLE1 t0 WHERE  t0.ZID = ? 
2010-02-05 01:57:51.097 app[393:207] CoreData: annotation: sql connection fetch time: 0.0046s
2010-02-05 01:57:51.100 app[393:207] CoreData: annotation: total fetch execution time: 0.0074s for 0 rows.
2010-02-05 01:57:51.125 app[393:207] CoreData: sql: SELECT <a bunch of fields> FROM ZTABLE2 t0 WHERE  t0.ZID = ? 
2010-02-05 01:57:51.129 app[393:207] CoreData: annotation: sql connection fetch time: 0.0040s
2010-02-05 01:57:51.132 app[393:207] CoreData: annotation: total fetch execution time: 0.0071s for 0 rows.

0.0071s للحصول على استفسار على ما يرام على جهاز 3GS، ولكن إذا قمت بإضافة 100 من هذه الأمر، فقد حصلت للتو على حظر 700ms.

في التعليمات البرمجية الخاصة بي، أستخدم مساعد للقيام بهذه الجدوى:

- (MyObject *) myObjectById:(NSNumber *)myObjectId {
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:[self objectEntity]]; // my entity cache    
    [fetchRequest setPredicate:[self objectPredicateById:objectId]]; // predicate cache    
    NSError *error = nil;
    NSArray *fetchedObjects = [moc executeFetchRequest:fetchRequest error:&error];
    if ([fetchedObjects count] == 1) {
        [fetchRequest release];
        return [fetchedObjects objectAtIndex:0];
    }
    [fetchRequest release];
    return nil;
}

MyObject *obj = [self myObjectById];
if (!obj) {
   // [NSEntityDescription insertNewObjectForEntityForName: ... etc
}

أشعر أن هذا خطأ ويجب أن أفعل التحقق بطريقة أخرى. يجب أن تضرب فقط قاعدة البيانات مرة واحدة وينبغي أن تأتي من الذاكرة بعد ذلك، أليس كذلك؟ (يتم تنفيذ SQL حتى بالنسبة للكائنات التي أعرفها بالتأكيد موجودة محليا ويجب تحميلها على الذاكرة مع الاستفسارات السابقة.) ولكن، إذا كان لدي سوى Myobjectid من مصدر خارجي، فهذا هو أفضل ما يمكن أن أفكر فيه.

لذلك، ربما السؤال هو: إذا كان لدي myobjectid (بيانات أساسية INT64 على myoBject)، كيف يمكنني التحقق بشكل صحيح ما إذا كان الكائن المحلي ذي الصلة موجود في مخزن الأقراص المضغوطة أم لا؟ التحميل المسبق مجموعة كاملة من المباريات الممكنة ثم المسند صفيف محلي؟

(حل واحد ممكن هو نقل هذا إلى سلسلة خلفية. سيكون هذا جيدا، إلا أنه عندما أحصل على التغييرات من الخيط والقيام [MOC MERGECHANGESFROMCONTEXTEDSEVENTIDEDIDEDIDEDIDEDITIDEDITIONIDEDIDIFITIONTIDESTIDESTIONITIONITIONTIONITIONITIONTIONITIONTIONITIONTIONTIONTIONTIONTIONDE لا تزال كتل.)

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

المحلول

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

أساسا تحتاج إلى إنشاء مجموعة من المعرفات أو الخصائص مثل الأسماء، أو أي شيء لديك من كيان الكائن المدار.

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

[fetchRequest setPredicate:[NSPredicate predicateWithFormat: @"(objectID IN %@)", objectIDs]];

بالطبع "Opsidss" يمكن أن يكون أي شيء يمكنك استخدامه لتحديده. لا يجب أن يكون nsmanagedobjectid.

ثم يمكنك القيام بطلب جلب واحد، وتكرر الكائنات المنفجرة الناتجة، للعثور على التكرارات. إضافة واحدة جديدة إذا لم تكن موجودة.

نصائح أخرى

ربما يمكن أن تأخذ درسا من عملاء البريد الإلكتروني.

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

إذا كان هناك فرق، فإنه يأخذ أحد الإجراءاتين. 1. إذا كان موجودا على العميل، ولكن ليس الخادم ونحن IMAP، ثم حذف محليا. 2. إذا كان موجودا على الخادم، ولكن ليس العميل، ثم قم بتنزيل بقية الرسالة.

في حالتك، الاستعلام الأول لجميع المعايير. ثم أرسل استعلام متابعة للاستيلاء على جميع البيانات الخاصة بالأخرى التي ليس لديك بالفعل.

إذا كان لديك موقف قد يكون فيه السجل محليا، لكن ربما تم تحديثه منذ آخر تنزيل على الخادم، فيجب أن يتضمن استفسارك التاريخ الأخير المحدث.

يجب عليك القيام بإحضار واحد عبر جميع الكائنات، ولكن فقط جلب معرف الخادم فقط للكائنات.

يستخدم setpropertiestifetch: مع setresulttype: ضبط ل NSDictionaryResultType.

يبدو أن ما تحتاجه هو nsset of nsmanagedobjects التي يتم تحميلها في الذاكرة أو تخزينها في مكان ما بسرعة أكبر من متجرك المستمر.

بهذه الطريقة يمكنك مقارنة معرفات الكائنات من الشبكة مع معرفات الكائنات من ذاكرة التخزين المؤقت الخاصة بك دون الحاجة إلى إجراء طلب جلب على مجموعة بيانات كبيرة.

ربما أضف المعرف إلى ذاكرة التخزين المؤقت من داخل -awakefrominsert داخل فئات الكيان المدارة؟

بعد القتال مع هذه المشكلة نفسها لأعمار، تعثرت أخيرا عبر إدخال المدونة هذا الذي حله تماما (وهو كتلة شفرة قابلة لإعادة الاستخدام كمكافأة!).

http://henrik.nyh.se/2007/01/AMPorting-Legacy-Data-into-Core-Data-With-Find-or-or-or-or-delete-pattern.

في حين أن نموذج التعليمات البرمجية لا يغطي جزء الشبكة؛ تحتاج ببساطة إلى تحميلها في nsdictionary. ثم يتناول هذا مزامنة سياق البيانات الأساسية المحلية.

ليس إجابة، ولكن عنوان URL محدث لوثائق "استيراد البيانات" بكفاءة

http://developer.apple.com/library/mac/#documentation/cocoa/conectual/coredata/acticles/cdimporting.html#//apple_ref/doc/uid/tp40003174-sw1.

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