سؤال

أنا أكتب حاليًا تطبيقًا يحتاج إلى القدرة على تعديل واستمرار أجزاء مختلفة من البيانات. لقد قررت استخدام البيانات الأساسية لهذا الغرض. عندما يفتح المستخدم التطبيق لأول مرة ، أحتاج إلى استيراد كمية كبيرة من البيانات من قاعدة بيانات SQLite ، تتكون هذه البيانات من العلاقات العديدة إلى العدد.

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

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

الرمز الذي أستخدمه الآن:

- (void)importEntitiesIntoContext: (NSManagedObjectContext*)managedObjectContext
{
    // Setup the database object
    static NSString* const databaseName = @"DBName.sqlite";
    NSString* databasePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent: databaseName];

    sqlite3* database;

    // Open the database from the user's filessytem
    if ( sqlite3_open_v2( [databasePath UTF8String], &database, SQLITE_OPEN_READONLY, NULL ) == SQLITE_OK ) 
    {
        // Setup the SQL Statement
        NSString* sqlStatement = [NSString stringWithFormat: @"SELECT some_columns FROM SomeTable;"];

        sqlite3_stmt* compiledStatement;
        if ( sqlite3_prepare_v2( database, [sqlStatement UTF8String], -1, &compiledStatement, NULL ) == SQLITE_OK ) 
        {
            // Create objects to test for existence of exercises
            NSPredicate* predicate = [NSPredicate predicateWithFormat: @"something == $SOME_NAME"];

            NSEntityDescription* entityDescription = [NSEntityDescription entityForName: @"SomeEntity" 
                                                                 inManagedObjectContext: managedObjectContext];
            NSFetchRequest* fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
            [fetchRequest setEntity: entityDescription];

            // Loop through the results and add them to the feeds array
            while ( sqlite3_step( compiledStatement ) == SQLITE_ROW ) 
            {
                NSString* someName = [NSString stringWithCharsIfNotNull: (char*)sqlite3_column_text( compiledStatement, 1 )];
                NSPredicate* localPredicate = [predicate predicateWithSubstitutionVariables: 
                                               [NSDictionary dictionaryWithObject: someName
                                                                           forKey: @"SOME_NAME"]];
                [fetchRequest setPredicate: localPredicate];

                NSError* fetchError;
                NSArray* array = [managedObjectContext executeFetchRequest: fetchRequest 
                                                                     error: &fetchError];
                if ( array == nil )
                {
                    // handle error
                }
                else if ( [array count] == 0 )
                {
                    SomeEntity* entity = 
                    [NSEntityDescription insertNewObjectForEntityForName: @"SomeEntity"
                                                  inManagedObjectContext: managedObjectContext];
                    entity.name = someName;

// **here I call a method that attempts to add the relationships(listed below)**

                }
                else
                {
                    // Some entity already in store
                }

            }
        }
        else
        {
            NSLog( @"sqlStatement failed: %@", sqlStatement );
        }

        // Release the compiled statement from memory
        sqlite3_finalize( compiledStatement );
    }

    // All the data has been imported into this temporary context, now save it
    NSError *error = nil;
    if ( ![managedObjectContext save: &error] ) 
    {
        NSLog( @"Unable to save %@ - %@", [error localizedDescription] );
    }
}

طريقة لإضافة العلاقات:

- (void)setRelationshipForEntity: (Entity*)entity 
            inManagedObjectContext: (NSManagedObjectContext*)managedObjectContext 
                     usingDatabase: (sqlite3*)database
                        entityId: (NSNumber*)entityId
{

    // Setup the SQL Statement and compile it for faster access
    NSString* sqlStatement = [NSString stringWithFormat: @"SELECT Relationship.name FROM Relationship JOIN Entitys_Relationship ON Entitys_Relationship.id_Relationship = Relationship.id JOIN Entitys ON Entitys_Relationship.id_Entitys = Entitys.id WHERE Entitys.id = %d;", [entityId integerValue]];

    sqlite3_stmt* compiledStatement;
    if ( sqlite3_prepare_v2( database, [sqlStatement UTF8String], -1, &compiledStatement, NULL ) == SQLITE_OK ) 
    {
        // Create objects to test for existence of relationship
        NSPredicate* predicate = [NSPredicate predicateWithFormat: @"relationshipName == $RELATIONSHIP_NAME"];

        NSEntityDescription* entityDescription = [NSEntityDescription entityForName: @"EntityRelationship" 
                                                             inManagedObjectContext: managedObjectContext];
        NSFetchRequest* fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
        [fetchRequest setEntity: entityDescription];

        while ( sqlite3_step( compiledStatement ) == SQLITE_ROW ) 
        {
            NSString* relationshipName = [NSString stringWithCharsIfNotNull: (char*)sqlite3_column_text( compiledStatement, 0 )];
            NSPredicate* localPredicate = [predicate predicateWithSubstitutionVariables: 
                                           [NSDictionary dictionaryWithObject: relationshipName
                                                                       forKey: @"RELATIONSHIP_NAME"]];
            [fetchRequest setPredicate: localPredicate];

            NSError* fetchError;
            NSArray* array = [managedObjectContext executeFetchRequest: fetchRequest 
                                                                 error: &fetchError];
            if ( array == nil )
            {
                // handle error
            }
            else if ( [array count] == 0 )
            {
                EntityRelationship* entityRelationship = 
                [NSEntityDescription insertNewObjectForEntityForName: @"EntityRelationship"
                                              inManagedObjectContext: managedObjectContext];
                entityRelationship.relationshipName = relationshipName;

                [entity addRelationshipObject: entityRelationship];
                //NSLog( @"Inserted relationship named %@", relationshipName );
            }
            else
            {
                [entity addRelationship: [NSSet setWithArray: array]];
            }
        }
    }
    else
    {
        NSLog( @"slqStatement failed: %@", sqlStatement );
    }

    // Release the compiled statement from memory
    sqlite3_finalize( compiledStatement );  
}
هل كانت مفيدة؟

المحلول

من أين تأتي قاعدة البيانات الأصلية؟

عادةً ما تقوم بتحويل جميع بياناتك إلى البيانات الأساسية أثناء التطوير ، ثم شحن التطبيق باستخدام متجر بيانات أساسي مسبقًا (لا حاجة للمستخدم لانتظار الاستيراد).

نصائح أخرى

لدى Apple بعض الاقتراحات حول كيفية تحسين الواردات الكبيرة في متجر بيانات أساسي:

  • تعطيل مديرة التراجع أثناء استيراد الدفعة
  • لا تقم بإدراج سجل على حدة-قم بإنشاء مجموعات من الحجم N (اعتمادًا على حجم السجل)
  • استخدم حمام سباحة Autorelease محليًا واستنزفه بعد كل دفعة

انظر توثيق للحصول على التفاصيل.

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