La database Sqlite3 en iPhone se bloquea, ¿cómo evitarla?

Tengo una consulta que realiza una búsqueda en un DB de Sqlite3. No hace más que leer usando un lector. Para cada coincidencia encontrada, llama a una callback a la interfaz de usuario que actualiza una vista de resultados.

Mientras se ejecuta esta búsqueda, presiono un button en la interfaz de usuario que realizará otra acción en un nuevo hilo. Al final se supone que debe eliminar la vista del controller de búsqueda y mostrar un nuevo controller.

Sin embargo, en algún momento la acción desencadenada quiere escribir en la database. Y allí simplemente se cuelga y, finalmente, veré una exception de que el DB está bloqueado.

Es interesante también que el lector de búsqueda no continúe, es un punto muerto.

¿Debo abrir la database de alguna manera especial para admitir el uso de multiprocesss? ¿Cuál sería el constructor para la connection?

MonoTouch 5.1+ proporciona una API que le permite seleccionar el model de subprocesss que se utilizará con SQLite.

SqliteConnection.SetConfig (SQLiteConfig.MultiThread); 

Esto se corresponde con algunas de las opciones de connection de la biblioteca SQLite.

ACTUALIZACIÓN: si está utilizando una versión anterior de MonoTouch (por ejemplo, entre 4.2 y 5.0.x), puede usar el binary adjunto al informe de error # 652 (siga las instrucciones) o copyr y pegar el parche (p / invoke y enum ) dentro de su propia aplicación.

No estoy seguro de que interprete tu descripción correctamente, pero la forma en que lo describes, me parece que tu "lector" pasa a través de la database fila por fila y cada vez que encuentra un resultado hace una callback a una callback ¿function? ¿Es esto correcto?

Si ese es el caso, puede bloquear repetidamente su database y su búsqueda será lenta.

La forma correcta es extraer todas las coincidencias en un set de resultados en una única consulta: una vez que se complete esa consulta, se liberará el locking y tendrá un set de resultados de SQL que solo contiene las filas correspondientes.

Dejará que SQLite cree un set de resultados como este mediante el uso de una consulta del tipo "SELECT * FROM tablename WHERE columnX LIKE '% searchstring%'"

(o similar, según sus criterios de búsqueda)

Esto creará un set de resultados con todas las coincidencias en la database y luego liberará el locking de la database. Luego, puede ver el resultado y crear objects y poner en NSArray que está conectado a su vista de interfaz de usuario.

 NSArray retval = [NSMutableArray array]; //Create a query NSString *query = [NSString stringWithFormat:@"SELECT * FROM %@ WHERE %@ LIKE %@", tableName, columnName, searchString]; sqlite3_stmt *statement; //Database locks here if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, nil) == SQLITE_OK) { //Database should unlock here, the query is finished while (sqlite3_step(statement) == SQLITE_ROW) { char *nameChars = (char *) sqlite3_column_text(statement, 0); NSString *name = [NSString stringWithUTF8String:nameChars]; SomeClass *info = [[SomeClass alloc] initWithName:name]; /* Extract other columns and put in your object */ [retval addObject:info]; [info release]; } sqlite3_finalize(statement); } else { NSLog(@"SQL-statement failed"); } 

Hacer esto no debería ser un problema para escribir en el DB cuando sea necesario. Solo realice nuevas consultas al DB cuando sea absolutamente necesario, por ejemplo, cuando se modifiquen sus criterios de búsqueda o se haya actualizado el contenido del DB.

No ejecute consultas repetidas a un DB que no haya cambiado, o con criterios de búsqueda sin cambios.