2016-07-22 8 views
0

Ich bekomme Fehler Datenbank gesperrt. beim ersten Versuch fügt es die Zeile, aber danach bekomme ich den Fehler database locked.Fehler beim Datenbank-Locking beim zweiten Hinzufügen der Zeile

Ich versuche, Web-Seite-Saver so zu machen, beim ersten Laden, wenn App lädt, fügt die Zeile hinzu, aber wenn ich wieder versuche, jede Webseite zu speichern, wird es nicht gespeichert und ich bekomme die Fehlerdatenbank gesperrt.

Auch die Löschung ist auch nicht nach dem Speichern einer Webseite passiert.

#import "DBManager.h" 
static DBManager *sharedInstance = nil; 
static sqlite3 *database = nil; 
static sqlite3_stmt *statement = nil; 

@implementation DBManager 

+(DBManager*)getSharedInstance{ 
if (!sharedInstance) { 
    sharedInstance = [[super allocWithZone:NULL]init]; 
    [sharedInstance createDB]; 
} 
return sharedInstance; 
} 

-(BOOL)createDB{ 
NSString *docsDir; 
NSArray *dirPaths; 
// Get the documents directory 
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
docsDir = dirPaths[0]; 
// Build the path to the database file 
databasePath = [[NSString alloc] initWithString:[docsDir stringByAppendingPathComponent: @"browser.db"]]; 

BOOL isSuccess = YES; 
NSFileManager *filemgr = [NSFileManager defaultManager]; 
if ([filemgr fileExistsAtPath: databasePath ] == NO) 
{ 
    const char *dbpath = [databasePath UTF8String]; 
    if (sqlite3_open(dbpath, &database) == SQLITE_OK) 
    { 
     char *errMsg; 
     NSLog(@"insod"); 
     const char *sql_stmt ="create table if not exists list(sno int primary key,name varchar(50),category varchar(30),path varchar(500),fav int)"; 
     if (sqlite3_exec(database, sql_stmt, NULL, NULL, &errMsg) 
      != SQLITE_OK) 
     { 
      isSuccess = NO; 
      NSLog(@"Failed to create table"); 
     } 
     sqlite3_close(database); 
     return isSuccess; 
    } 
    else { 
     isSuccess = NO; 
     NSLog(@"Failed to open/create database"); 
    } 
}else{ 
    NSLog(@"File Exist"); 
} 
return isSuccess; 
} 

-(BOOL) Delete:(NSString *) name{ 
const char *dbpath = [databasePath UTF8String]; 
if (sqlite3_open(dbpath, &database) == SQLITE_OK){ 
    NSString *query = [NSString stringWithFormat:@"delete from list where name like '%@'",name]; 
    const char *stmt = [query UTF8String]; 
    sqlite3_prepare_v2(database, stmt,-1, &statement, NULL); 
    if (sqlite3_step(statement) == SQLITE_DONE){ 
     sqlite3_finalize(statement); 
     return YES; 
    }else { 
     NSLog(@"error: %s",sqlite3_errmsg(database)); 
     sqlite3_finalize(statement); 
     return NO; 
    } 

}else{ 
    sqlite3_close(database); 
    return NO; 
} 

} 

-(NSDictionary *) CatList:(NSString *) cat{ 
const char *dbpath = [databasePath UTF8String]; 
NSDictionary *dict; 
if (sqlite3_open(dbpath, &database) == SQLITE_OK) 
{ 

    NSString *querySQL =[NSString stringWithFormat:@"select name,path from list where category like '%@'",cat]; 
    const char *query_stmt = [querySQL UTF8String]; 

    if (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK) 
    { 
     // NSLog(@"inside list"); 

     NSMutableArray *arr1 = [[NSMutableArray alloc] init]; 
     NSMutableArray *arr2 = [[NSMutableArray alloc] init]; 
     //   NSMutableArray *arr3 = [[NSMutableArray alloc] init]; 
     while(sqlite3_step(statement) == SQLITE_ROW) 
     { 

      NSString *name = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)]; 
      [arr1 addObject:name]; 
      //NSLog(@"%@",name); 
      NSString *category = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)]; 
      [arr2 addObject:category]; 
      //    //NSLog(@"%@",dept); 
      //    NSString *path = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 3)]; 
      //    [arr3 addObject:path]; 
     } 
     sqlite3_finalize(statement); 
     dict = @{@"name":arr1,@"path":arr2}; 
     //NSLog(@"%@",dict); 
    }else{ 
     NSLog(@"error: %s",sqlite3_errmsg(database)); 
    } 
    sqlite3_close(database); 
} 
return dict; 
} 

- (BOOL) saveData:(NSString*)name category:(NSString*)category path:(NSString*)path{ 
const char *dbpath = [databasePath UTF8String]; 
if (sqlite3_open(dbpath, &database) == SQLITE_OK) 
{ 

    NSString *highest = @"select max(sno) from list"; 
    const char *Query = [highest UTF8String]; 

    if (sqlite3_prepare_v2(database, Query, -1, &statement, NULL) == SQLITE_OK){ 
     if (sqlite3_step(statement) == SQLITE_ROW){ 
      int sno = sqlite3_column_int(statement, 0); 
      NSString *insertSQL = [NSString stringWithFormat:@"insert into list values(\"%d\",\"%@\",\"%@\", \"%@\",\"%d\")",sno+1,name, category, path,0]; 
      const char *insert_stmt = [insertSQL UTF8String]; 
      sqlite3_prepare_v2(database, insert_stmt,-1, &statement, NULL); 
      if (sqlite3_step(statement) == SQLITE_DONE){ 
       sqlite3_finalize(statement); 
       return YES; 
      }else { 
       sqlite3_finalize(statement); 
       return NO; 
      } 

     }else{ 
      NSString *insertSQL = [NSString stringWithFormat:@"insert into list values(\"%d\",\"%@\",\"%@\", \"%@\",\"%d\")",1,name, category, path,0]; 
      const char *insert_stmt = [insertSQL UTF8String]; 
      sqlite3_prepare_v2(database, insert_stmt,-1, &statement, NULL); 
      if (sqlite3_step(statement) == SQLITE_DONE){ 
       sqlite3_finalize(statement); 
       return YES; 
      }else { 
       sqlite3_finalize(statement); 
       return NO; 
      } 
     } 
    } 
    sqlite3_close(database); 
} 
return NO; 
} 

-(BOOL) Fav:(NSString *) name{ 
const char *dbpath = [databasePath UTF8String]; 
if (sqlite3_open(dbpath, &database) == SQLITE_OK){ 
    NSString *query = [NSString stringWithFormat:@"update list set fav = 1 where name like '%@'",name]; 
    const char *stmt = [query UTF8String]; 
    sqlite3_prepare_v2(database, stmt,-1, &statement, NULL); 
    if (sqlite3_step(statement) == SQLITE_DONE){ 
     sqlite3_finalize(statement); 
     return YES; 
    }else { 
     sqlite3_finalize(statement); 
     return NO; 
    } 
}else{ 

    return NO; 
} 
} 

-(NSArray *) GetListFav{ 
const char *dbpath = [databasePath UTF8String]; 
NSArray *dict; 
if (sqlite3_open(dbpath, &database) == SQLITE_OK) 
{ 

    NSString *querySQL = @"select name from list where fav = 1"; 
    const char *query_stmt = [querySQL UTF8String]; 

    if (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK) 
    { 
     NSMutableArray *arr1 = [[NSMutableArray alloc] init]; 
     while(sqlite3_step(statement) == SQLITE_ROW) 
     { 
      NSString *name = [[NSString alloc] initWithUTF8String:    (const char *) sqlite3_column_text(statement, 0)]; 
      [arr1 addObject:name]; 
     } 
     sqlite3_finalize(statement); 
     dict = arr1; 
    }else{ 
     NSLog(@"error: %s",sqlite3_errmsg(database)); 
    } 
    sqlite3_close(database); 
} 
return dict; 
} 

-(BOOL) removeFav:(NSString *) name{ 
const char *dbpath = [databasePath UTF8String]; 
if (sqlite3_open(dbpath, &database) == SQLITE_OK){ 
    NSString *query = [NSString stringWithFormat:@"update list set fav = 0 where name like '%@'",name]; 
    const char *stmt = [query UTF8String]; 
    sqlite3_prepare_v2(database, stmt,-1, &statement, NULL); 
    if (sqlite3_step(statement) == SQLITE_DONE){ 
     sqlite3_finalize(statement); 
     return YES; 
    }else { 
     sqlite3_finalize(statement); 
     return NO; 
    } 

}else{ 
    return NO; 
} 
} 

-(NSArray *) GetList{ 
const char *dbpath = [databasePath UTF8String]; 
NSArray *dict; 
if (sqlite3_open(dbpath, &database) == SQLITE_OK) 
{ 

    NSString *querySQL = @"select name from list"; 
    const char *query_stmt = [querySQL UTF8String]; 

    if (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK) 
    { 
     //NSLog(@"inside list"); 

     NSMutableArray *arr1 = [[NSMutableArray alloc] init]; 
     while(sqlite3_step(statement) == SQLITE_ROW) 
     { 
      NSString *name = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)]; 
      [arr1 addObject:name]; 
     } 
     sqlite3_finalize(statement); 
     dict = arr1; 
    }else{ 
     NSLog(@"error: %s",sqlite3_errmsg(database)); 
    } 
    sqlite3_close(database); 
} 
return dict; 
    } 

@end 

Antwort

0

Sie können nur einmal auf sqllite zugreifen. Wenn Sie mehrere Threads haben, können Sie in dieser Situation ausführen. Beispiel:

Also immer versuchen Datenbank zu schließen, sobald es mit verwendet wird:

sqlite3_close(database); 
0

Sie sicherstellen müssen, dass jeder sqlite3_open mit einem sqlite3_close ausgeglichen ist, bevor Sie versuchen sqlite3_open wieder zu tun:

  1. Ihre saveData-Methode verfügt über einige return-Anweisungen, die verhindern, dass die Datenbank jemals sqlite3_close aufruft. Stellen Sie sicher, dass alle Pfade der Methode die Datenbank ordnungsgemäß schließen. Am Ende bedeutet dies, dass Sie versuchen werden, die Datenbank zu öffnen, obwohl sie bereits geöffnet ist.

    Oder, besser, öffnen Sie einfach die Datenbank und lassen Sie sie geöffnet, wodurch das wiederholte Öffnen und Schließen der Datenbank entfällt.

  2. Ihre Methoden Delete, und removeFav schließen die Datenbank auch nicht.

Einige unabhängige Beobachtungen:

  1. Sie sollten über die Verwendung von stringWithFormat vorsichtig sein, SQL mit String-Parameter zu bauen. Wenn die gesuchte Zeichenfolge einen Apostroph enthält, schlägt der Code fehl. Verwenden Sie ? Platzhalter und verwenden Sie dann sqlite3_bind_text, um Werte an diese Platzhalter zu binden.

  2. Wenn Sie Ihre sno Spalte eine AUTOINCREMENT machen, müssen Sie das nicht tun "Holen Sie die maximale Sno vor dem Einfügen neuer Zeile" Logik. So könnte die CREATE Aussage wie folgt aussehen:

    create table if not exists list (
        sno integer primary key autoincrement, 
        name text, 
        category text, 
        path text, 
        fav integer) 
    

    Sie dann sno aus den INSERT Aussagen weglassen kann, und es wird automatisch eine eindeutige Kennung zugewiesen werden.

Verwandte Themen