Я использую два разных типа подключений fmdb в своем приложении:
FMDatabase для всех запросов READ и FMDatabaseQueue для всех запросов UPDATE.
Оба обрабатываются одним синглэном, который сохраняет оба типа открытыми все время, пока приложение работает.
Оба, чтение и обновление запросов, используются в разных потоках, поскольку некоторые задачи в моем приложении продвигаются в фоновом режиме; как получение данных с сервера и вставка их в db через FMDatabaseQueue в собственный фоновый поток - при чтении некоторой информации из db через FMDatabase и обновлении ViewController с ней в основном потоке.
Моя проблема в том, что после вставки данных в db через FMDatabaseQueue второе соединение (FMDatabase) не возвращает обновленную информацию, поскольку она не находит их. Но я знаю, что данные были вставлены, поскольку я проверил db с помощью инструмента браузера db + ошибок при вставке. Чтобы этого избежать, мне нужно закрыть соединение с FMDatabase db и снова открыть его, чтобы увидеть изменения, сделанные другим соединением. К сожалению, когда мое приложение запускается, есть много вложений, обновления + читаются, так как множество новых данных загружается с сервера, который необходимо обработать, - поэтому закрытие и открытие db каждый раз, когда было произведено обновление, происходит во многих "занятых базами данных", сообщения.
Я использовал один единственный FMDatabaseQueue для всех потоков и выполнял (чтение, обновление) до этого, но было довольно медленно при использовании запросов чтения с переменными __block, чтобы получить результат из обратного вызова, в то время как другой поток выполняет некоторые вставки (между 50- 100 в одной транзакции).
Вдобавок к этому база данных зашифровывается через sqlcipher - не уверен, важно ли это, но хочу упомянуть об этом. Поэтому каждый раз, когда мне приходится закрывать и открывать базу данных, я делаю setKey.
Мой вопрос: возможно ли использовать установку с двумя разными типами соединений для нескольких потоков, и, если да, мне нужно закрыть и открыть соединение с FMDatabase? Или есть лучшее решение для этой утилиты?
UPDATE
Мой код для выполнения вставки/обновления выглядит как
-(void) create:(NSArray *)transactions
{
NSMutableString *sqlQuery = [[NSMutableString alloc] initWithString:STANDARD_INSERT_QUERY];
[sqlQuery appendString:@"(transaction_id, name, date) VALUES (?,?,?)"];
FMDBDataSource *ds = [FMDBDataSource sharedManager];
FMDatabaseQueue *queue = [ds getFMDBQ];
[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
[db setKey:[ds getKey]]; // returns the key to decrypt the database
for (Transaction *transaction in transactions)
{
[db executeUpdate:sqlQuery, transaction.transactionId, transaction.name, transaction.date];
}
}];
}
и запрос чтения
-(Transaction *)read:(NSString *)transactionId
{
NSString *sqlQuery = [[NSString alloc] initWithString:STANDARD_SELECT_QUERY];
Transaction *transaction = nil;
FMDBDataSource *ds = [FMDBDataSource sharedManager];
FMResultSet *rs = [[ds getFMDB] executeQuery:sqlQuery];
while ([rs next]) {
transaction = [[Transaction alloc] init];
[transaction setTransactionId:[rs stringForColumn:@"transaction_id"]];
[transaction setName:[rs stringForColumn:@"name"]];
}
[rs close];
return transaction;
}
Источник FMDBDataSource является одноэлементным, содержащим как FMDatabase, так и FMDatabaseQueue, соединения
- (FMDatabaseQueue *)getFMDBQ
{
if (self.fmdbq == nil)
{
self.fmdbq = [FMDatabaseQueue databaseQueueWithPath:[self getDBPath]];
}
return self.fmdbq;
}
- (FMDatabase *) getFMDB
{
if(self.fmdb == nil)
{
self.fmdb = [FMDatabase databaseWithPath:[self getDBPath]];
[self openAndKeyDatabase]; // opens the db and sets the key as the db is encrypted
}
return self.fmdb;
}
Как я уже говорил, при использовании этого кода соединение FMDatabase не получает информацию, которая была вставлена через FMDatabaseQueue.