База данных Sqlite3 в iPhone блокируется - как избежать? - PullRequest
3 голосов
/ 30 ноября 2011

У меня есть запрос, который выполняет поиск в БД Sqlite3. Он не делает ничего, кроме чтения с использованием ридера. Для каждого найденного совпадения он вызывает обратный вызов пользовательского интерфейса, который обновляет представление результатов.

Пока идет поиск, я нажал кнопку в пользовательском интерфейсе, которая выполнит какое-то другое действие в новом потоке. В конце концов предполагается удалить вид контроллера поиска и показать новый контроллер.

Однако в какой-то момент вызванное действие хочет записать в базу данных. И там он просто зависает, и в конце концов я увижу исключение, что БД заблокирована.

Интересно также, что поиск читателя также не продолжается, это тупик.

Нужно ли открывать базу данных каким-то особым образом для поддержки многопоточного использования? Каким будет конструктор соединения?

Ответы [ 2 ]

1 голос
/ 01 декабря 2011

Я не уверен, что правильно истолковал ваше описание, но, как вы его описываете, мне кажется, что ваш «читатель» шаг за шагом просматривает базу данных и каждый раз, когда находит результат, выполняет обратный вызов.к функции обратного вызова?Это правильно?

Если это так, вы можете несколько раз заблокировать вашу БД, и ваш поиск будет медленным.

Правильный способ - извлечь все совпадения в набор результатов в одномодин запрос - как только этот запрос будет завершен, блокировка будет снята, и у вас будет набор результатов из SQL, который содержит только совпадающие строки.

Вы можете позволить SQLite создать набор результатов, подобный этому, используя запрос типа"SELECT * FROM tablename WHERE columnX LIKE '% searchstring%'"

(или аналогичный, в зависимости от ваших критериев поиска)

Это создаст набор результатов со всеми совпадениями в базе данных, а затемснять блокировку базы данных.Затем вы можете пошагово просмотреть результат, создать объекты и поместить их в NSArray, который связан с вашим представлением пользовательского интерфейса.

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

При этом не должно возникнуть проблем с записью в БД, когда это необходимо.Выполняйте новые запросы к БД только тогда, когда это абсолютно необходимо, например, когда изменились критерии поиска или обновлено содержимое в БД.

Не запускайте повторные запросы к БД, которая не изменилась, или снеизменные критерии поиска.

1 голос
/ 30 ноября 2011

MonoTouch 5.1+ предоставляет API , позволяющий выбрать модель потоков, которая будет использоваться с SQLite.

SqliteConnection.SetConfig (SQLiteConfig.MultiThread);

Это сопоставляет с некоторыми из параметров подключения библиотеки SQLite.

ОБНОВЛЕНИЕ: Если вы используете более раннюю версию MonoTouch (например, между 4.2 и 5.0.x), вы можете использовать двоичный файл, прикрепленный к отчету об ошибке # 652 (следуйте инструкции) или скопируйте и вставьте патч (p / invoke и enum) в ваше собственное приложение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...