核心数据“Upsert”从SQLite数据库 [英] Core Data "Upsert" from SQLite Database

查看:143
本文介绍了核心数据“Upsert”从SQLite数据库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在撰写一个应用程式,需要能够修改和维持各种资料。我决定使用Core Data为此目的。
当用户第一次打开应用程序时,我需要从sqlite数据库导入大量数据,这个数据由多对多关系组成。

I am currently writing an App that needs the ability to modify and persist various pieces of data. I've decided to use Core Data for this purpose. When the user opens the Application for the first time I need to import a large amount of data from a sqlite database, this data consists of the many-to-many relationships.

我想找出将所有这些数据插入我的代码数据存储的最好方法。现在我使用一个NSOperation做导入,而应用程序的其余部分保持活动,所以用户可以做其他事情,但我想导入发生尽可能快,所以整个应用程序可以立即访问。

I'd like to find out the best way to insert all of this data into my code data store. Right now I am using an NSOperation to do the import while that rest of the application remains active, so the user can do other things, but I'd like the import to happen as quickly as possible so the entire App can be accessed right away.

我现在使用的方法是使用NSFetchRequest来尝试在数据存储中找到相关的实体,如果实体在那里我只是添加它作为关系,如果实体不在那里,我创建一个新的,并将其添加为关系。

The method that I'm using now is to use an NSFetchRequest to attempt to find the related entity in the data store, if the entity is there I just add it as a relationship, if the entity is not there I create a new one and add it as a relationship. This works, but I feel that it is probably not even close to optimal.

我现在使用的代码:

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


推荐答案

从?

通常,您在开发期间将所有数据转换为Core Data,然后使用预填充的Core Data存储运送应用程序(无需用户等待a import)。

Typically, you would convert all your data to Core Data during development and then ship the app with a pre-populated Core Data store (no need for a user to wait for an import).

这篇关于核心数据“Upsert”从SQLite数据库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆