База данных заблокирована в Sqlite

#iphone #objective-c #database #sqlite

#iPhone #objective-c #База данных #sqlite

Вопрос:

Я разрабатываю приложение для iPhone, когда я вставляю данные в базу данных, которую я получил "Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Error while inserting data. 'database is locked''" Error. , код :

 - (NSString *) getDBPath {        
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
        NSString *documentsDir = [paths objectAtIndex:0];
        return [documentsDir stringByAppendingPathComponent:@"Halal.sqlite"];
}

  (void) finalizeStatements {

            if (database) sqlite3_close(database);
            if (deleteStmt) sqlite3_finalize(deleteStmt);
            if (addStmt) sqlite3_finalize(addStmt);
            if (detailStmt) sqlite3_finalize(detailStmt);
            if (updateStmt) sqlite3_finalize(updateStmt);
}

- (void) gettingData:(NSString *)dbPath {

            NSLog(@"Data base path is %@",dbPath);
            if (sqlite3_open([dbPath UTF8String], amp;database) == SQLITE_OK)
            {
                const char *sql = "select * from Product";
                sqlite3_stmt *selectstmt;
                if(sqlite3_prepare_v2(database, sql, -1, amp;selectstmt, NULL) == SQLITE_OK) 
                {
                    while(sqlite3_step(selectstmt) == SQLITE_ROW)
                    {
        [membersInfoDict setValue:[NSString stringWithUTF8String:(char*)sqlite3_column_text(selectstmt, 0)] forKey:@"ProductName"];
                        [membersInfoDict setValue:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)] forKey:@"ProductBarcode"];
                        [membersInfoDict setValue:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 2)] forKey:@"ProductImage"];
                        [membersInfoDict setValue:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 3)] forKey:@"ProductIngredients"];
                        [membersInfoDict setValue:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 4)] forKey:@"ProductStatus"];


                        if(membersInfoDict)
                        {
                           [membersInfoArray addObject:membersInfoDict];
                           membersInfoDict = nil;
                        //  NSLog(@"Entered and return");
                            return;
                        }
                    }
                }            
            }

            else
                sqlite3_close(database); //Even though the open call failed, close the database connection to release all the memory.

}


- (void) addRecord:(NSMutableDictionary *)recordDict
{
            if (sqlite3_close(database))
            {
                NSLog(@"Closed");
                NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
                NSString *documentsDir = [paths objectAtIndex:0];

                [self gettingData:[documentsDir stringByAppendingPathComponent:@"Halal.sqlite"]];                   
            }   
            else {
                NSLog(@"Not Closed");
            }               
            if(addStmt == nil) {
                const char *sql = "insert into Product(ProductName, ProductBarcode , ProductImage,ProductIngredients,ProductStatus ) Values(?,?,?,?,?)";
                if(sqlite3_prepare_v2(database, sql, -1, amp;addStmt, NULL) != SQLITE_OK)
                    NSAssert1(0, @"Error while creating add statement. '%s'", sqlite3_errmsg(database));
            }

            sqlite3_bind_text(addStmt, 1, [[recordDict objectForKey:@"ProductName"] UTF8String], -1, SQLITE_TRANSIENT);
            sqlite3_bind_text(addStmt, 2, [[recordDict objectForKey:@"ProductBarcode"] UTF8String], -1, SQLITE_TRANSIENT);
            sqlite3_bind_text(addStmt, 3, [[recordDict objectForKey:@"ProductImage"] UTF8String], -1, SQLITE_TRANSIENT);
            sqlite3_bind_text(addStmt, 4, [[recordDict objectForKey:@"ProductIngredients"] UTF8String], -1, SQLITE_TRANSIENT);
            sqlite3_bind_text(addStmt, 5, [[recordDict objectForKey:@"ProductStatus"] UTF8String], -1, SQLITE_TRANSIENT);


            if(SQLITE_DONE != sqlite3_step(addStmt))
                NSAssert1(0, @"Error while inserting data. '%s'", sqlite3_errmsg(database));
            else
            //SQLite provides a method to get the last primary key inserted by using sqlite3_last_insert_rowid
                rowID = sqlite3_last_insert_rowid(database);
            NSLog(@"last inserted rowId = %d",rowID);

            //Reset the add statement.
            sqlite3_reset(addStmt);
            //sqlite3_commit_hook();
            //sqlite3_commit_hook(addStmt,[NSString stringWithFormat:@"%d",rowID],database);

}
  

Пожалуйста, дайте мне решение для этого.
Большое спасибо…

Комментарии:

1. где вы открываете [ «database» sqlite3 * ] и есть ли какой-то другой запрос, который вы использовали, и он все еще сохраняет этот открытым?

2. я открываю базу данных при отображении сведений

Ответ №1:

Найдите комментарий //ADD THIS LINE TO YOUR CODE следующим вашим модифицированным методом.

 - (void) gettingData:(NSString *)dbPath {
    NSLog(@"Data base path is %@",dbPath);
    if (sqlite3_open([dbPath UTF8String], amp;database) == SQLITE_OK)
    {
        const char *sql = "select * from Product";
        sqlite3_stmt *selectstmt;
        if(sqlite3_prepare_v2(database, sql, -1, amp;selectstmt, NULL) == SQLITE_OK)
        {
            while(sqlite3_step(selectstmt) == SQLITE_ROW)
            {
                [membersInfoDict setValue:[NSString stringWithUTF8String:(char*)sqlite3_column_text(selectstmt, 0)] forKey:@"ProductName"];
                [membersInfoDict setValue:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)] forKey:@"ProductBarcode"];
                [membersInfoDict setValue:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 2)] forKey:@"ProductImage"];
                [membersInfoDict setValue:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 3)] forKey:@"ProductIngredients"];
                [membersInfoDict setValue:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 4)] forKey:@"ProductStatus"];

                if(membersInfoDict)
                {
                    [membersInfoArray addObject:membersInfoDict];
                    membersInfoDict = nil;
                    //  NSLog(@"Entered and return");
                    sqlite3_close(database);
                    return;
                }
            }
        }
        //ADD THIS LINE TO YOUR CODE
        sqlite3_finalize(selectstmt);
    }        
    else
        sqlite3_close(database); //Even though the open call failed, close the database connection to release all the memory.
}
  

Комментарии:

1. В случае, если (membersInfoDict) вы возвращаетесь, не освобождая базу данных. Вы должны включить туда sqlite3_close.

2. @Vincent следует ли вам закрывать базу данных при каждом обращении к ней? Кроме того, я использую метод [self openDB] для открытия базы данных. Имеет ли значение, что я разделяю функциональность или я должен делать все в одном месте. Кажется, что это не должно иметь значения.

3. Нет, нет необходимости закрывать базу данных каждый раз. Однако «хорошим программированием» является то, чтобы база данных была открыта и / или заблокирована как можно короче.

4. Добавление sqlite3_finalize(selectstmt); прямо над sqlite3_close (база данных); сработало для меня.

Ответ №2:

вам необходимо завершить скомпилированные инструкции, а затем закрыть базу данных, прежде чем открывать ее снова.

 sqlite3_finalize(compiledStatement);
sqlite3_close(database);
  

Ответ №3:

Приведенные выше ответы верны, однако есть способ, с помощью которого база данных показывает ошибку заблокирована, если мы работаем или отлаживаем на симуляторах.

Случай 1:

Здесь я объясняю сценарий, когда я вставляю данные в таблицу. И доступ к этой базе данных осуществляется любым браузером базы данных и осуществляется из симулятора.

Теперь, когда вы работаете над приложением через симулятор, поскольку вы сохранили данные в базе данных, данные сохранены. Теперь, если вы используете любой браузер для доступа к данным из этой базы данных, и если вы запускаете любую команду обновления в своем браузере и пытаетесь обновить любую строку, она преобразует эту строку в таблицу. (Теперь, когда мы пытаемся удалить что-либо из таблицы, всегда отображается сообщение о том, что в браузере предоставлены разрешения только для чтения и т.д.).

Теперь переходите к симулятору или, если вы снова запустите приложение и попытаетесь вставить какие-либо данные в эту таблицу, оно всегда покажет ошибку «База данных заблокирована», потому что разрешения доступны только для чтения, и мы изменили эти разрешения. Теперь, если вы попытаетесь изменить команды, как указано в ответах, вы всегда будете испытывать печаль. Всегда отображается ошибка, связанная с тем, что база данных заблокирована (поскольку я несколько раз пытался решить эту проблему, но каждый раз мне это не удавалось).

Есть только один способ выйти из этой ситуации: удалите приложение из вашего симулятора и переустановите его. И избегайте обновления / вставки какой-либо строки из браузера.

Другой ответ: случай 2:

Поскольку вы работаете в браузере sqlite и вносите в него какие-либо обновления, убедитесь, что вы сохранили все внесенные изменения, в противном случае произойдет блокировка.