2017-02-03 1 views
0

Я просматриваю наиболее распространенную проблему с запиранием базы данных.Как избежать ошибки «база данных заблокирована»?

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

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

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

-(void)insertIntoTable_VENUES_WithData:(NSArray*)dataArray{ 
sqlite3_stmt *statement = nil; 

const char *dbpath = [_databasePath UTF8String]; 
if (sqlite3_open(dbpath, &_database) == SQLITE_OK) { 

    const char *sql = "INSERT OR REPLACE INTO venues (gig_date, start_time, doors_open, end_time, gig_title, main_artist, gig_type, promoter, band_members, venue, tel_no, postcode, img_url, ticket_price, booking_url, sold_out, venue_url, venue_biog, sync_flag) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; 

    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; 
    [dateFormat setLocale:[[StaticHelper sharedObject] usLocale]]; 

    if (sqlite3_prepare_v2(_database, sql, -1, &statement, NULL) == SQLITE_OK) { 

     for (int i=0; i<dataArray.count; i++) { 

      NSDictionary *dataDic = [NSDictionary dictionaryWithDictionary:[dataArray objectAtIndex:i]]; 


      if (![[dataDic objectForKey:kGigDate] isEqual:[NSNull null]]){ 

       NSString *dateStr = [dataDic objectForKey:kGigDate]; 
       [dateFormat setDateFormat:@"dd/MM/yyyy"]; 
       NSDate *dateFromString = [[NSDate alloc] init]; 
       dateFromString = [dateFormat dateFromString:dateStr]; 
       NSDate *dateWithoutTime = [[StaticHelper sharedObject] getDateWithOutTime:dateFromString]; 

       float dateToStore = [dateWithoutTime timeIntervalSince1970]; 
       sqlite3_bind_double(statement, 1, dateToStore); 

      } 

      else 
       sqlite3_bind_null(statement,1); 


      if (![[dataDic objectForKey:kStartTime] isEqual:[NSNull null]]) 
       sqlite3_bind_text(statement,2,[[dataDic objectForKey:kStartTime] UTF8String],-1,SQLITE_TRANSIENT); 
      else 
       sqlite3_bind_null(statement,2); 

      if (![[dataDic objectForKey:kDoorsOpen] isEqual:[NSNull null]]) 
       sqlite3_bind_text(statement,3,[[dataDic objectForKey:kDoorsOpen] UTF8String],-1,SQLITE_TRANSIENT); 
      else 
       sqlite3_bind_null(statement,3); 

      if (![[dataDic objectForKey:kEndTime] isEqual:[NSNull null]]) 
       sqlite3_bind_text(statement,4,[[dataDic objectForKey:kEndTime] UTF8String],-1,SQLITE_TRANSIENT); 
      else 
       sqlite3_bind_null(statement,4); 

      if (![[dataDic objectForKey:kGigTitle] isEqual:[NSNull null]]) 
       sqlite3_bind_text(statement,5,[[dataDic objectForKey:kGigTitle] UTF8String],-1,SQLITE_TRANSIENT); 
      else 
       sqlite3_bind_null(statement,5); 

      if (![[dataDic objectForKey:kMainArtist] isEqual:[NSNull null]]) 
       sqlite3_bind_text(statement,6,[[dataDic objectForKey:kMainArtist] UTF8String],-1,SQLITE_TRANSIENT); 
      else 
       sqlite3_bind_null(statement,6); 

      if (![[dataDic objectForKey:kGigType] isEqual:[NSNull null]]) 
       sqlite3_bind_text(statement,7,[[dataDic objectForKey:kGigType] UTF8String],-1,SQLITE_TRANSIENT); 
      else 
       sqlite3_bind_null(statement,7); 

      if (![[dataDic objectForKey:kPromoter] isEqual:[NSNull null]]) 
       sqlite3_bind_text(statement,8,[[dataDic objectForKey:kPromoter] UTF8String],-1,SQLITE_TRANSIENT); 
      else 
       sqlite3_bind_null(statement,8); 

      if (![[dataDic objectForKey:kBandMembers] isEqual:[NSNull null]]) 
       sqlite3_bind_text(statement,9,[[dataDic objectForKey:kBandMembers] UTF8String],-1,SQLITE_TRANSIENT); 
      else 
       sqlite3_bind_null(statement,9); 

      if (![[dataDic objectForKey:kVenue] isEqual:[NSNull null]]) 
       sqlite3_bind_text(statement,10,[[dataDic objectForKey:kVenue] UTF8String],-1,SQLITE_TRANSIENT); 
      else 
       sqlite3_bind_null(statement,10); 

      if (![[dataDic objectForKey:kTelNo] isEqual:[NSNull null]]) 
       sqlite3_bind_text(statement,11,[[dataDic objectForKey:kTelNo] UTF8String],-1,SQLITE_TRANSIENT); 
      else 
       sqlite3_bind_null(statement,11); 

      if (![[dataDic objectForKey:kPostCode] isEqual:[NSNull null]]) 
       sqlite3_bind_text(statement,12,[[dataDic objectForKey:kPostCode] UTF8String],-1,SQLITE_TRANSIENT); 
      else 
       sqlite3_bind_null(statement,12); 

      if (![[dataDic objectForKey:kImgUrl] isEqual:[NSNull null]]) 
       sqlite3_bind_text(statement,13,[[dataDic objectForKey:kImgUrl] UTF8String],-1,SQLITE_TRANSIENT); 
      else 
       sqlite3_bind_null(statement,13); 

      if (![[dataDic objectForKey:kTicketPrice] isEqual:[NSNull null]]) 
       sqlite3_bind_text(statement,14,[[dataDic objectForKey:kTicketPrice] UTF8String],-1,SQLITE_TRANSIENT); 
      else 
       sqlite3_bind_null(statement,14); 

      if (![[dataDic objectForKey:kBookingUrl] isEqual:[NSNull null]]) 
       sqlite3_bind_text(statement,15,[[dataDic objectForKey:kBookingUrl] UTF8String],-1,SQLITE_TRANSIENT); 
      else 
       sqlite3_bind_null(statement,15); 

      if (![[dataDic objectForKey:kSoldOut] isEqual:[NSNull null]]) 
       sqlite3_bind_text(statement,16,[[dataDic objectForKey:kSoldOut] UTF8String],-1,SQLITE_TRANSIENT); 
      else 
       sqlite3_bind_null(statement,16); 

      if (![[dataDic objectForKey:kVenueUrl] isEqual:[NSNull null]]) 
       sqlite3_bind_text(statement,17,[[dataDic objectForKey:kVenueUrl] UTF8String],-1,SQLITE_TRANSIENT); 
      else 
       sqlite3_bind_null(statement,17); 

      if (![[dataDic objectForKey:kVenueBlog] isEqual:[NSNull null]]) 
       sqlite3_bind_text(statement,18,[[dataDic objectForKey:kVenueBlog] UTF8String],-1,SQLITE_TRANSIENT); 
      else 
       sqlite3_bind_null(statement,18); 

      sqlite3_bind_int(statement, 19, 0);//// 

      if (sqlite3_step(statement) != SQLITE_DONE) { 
       NSLog(@"SQL execution failed in ZADDED_FOOD_ITEMS: %s", sqlite3_errmsg(_database)); 
      } 


      if (sqlite3_step(statement) == SQLITE_DONE) { 
       if (i == (dataArray.count - 1)) 
        sqlite3_finalize(statement); 

      }else{ 
       sqlite3_reset(statement); 
       NSLog(@"SQL execution failed: %s", sqlite3_errmsg(_database)); 
      } 
     }//for 
     sqlite3_finalize(statement); 

    }else{ 
     NSLog(@"Row insertion error(error in prepare!)"); 
    } 

sqlite3_finalize(statement);//finalize is to sqlite3_prepare_v2 as close is to sqlite3_open 
sqlite3_close(_database);; 

}else{ 
    NSLog(@"error in opening db"); 
} 

}

-(NSMutableArray *)getDataFromTable_VENUES_WhereGigDateIsEqualTo:(NSDate*)gigDate 

{

NSDate *dateWithoutTime = [[StaticHelper sharedObject] getDateWithOutTime:gigDate]; 
NSTimeInterval dateInterval = [dateWithoutTime timeIntervalSince1970] ; 
NSInteger intDateInterval = dateInterval; 

const char *dbpath = [_databasePath UTF8String]; 
NSMutableArray *queryResult = [NSMutableArray array]; 
sqlite3_stmt *statement = nil; 
NSMutableDictionary *dic; 

if (sqlite3_open(dbpath, &_database) == SQLITE_OK) 
{ 
    NSString *query = [NSString stringWithFormat:@" SELECT * FROM %@ WHERE %@='%ld' AND %@=1 ORDER BY %@ ASC ",kVenues, kGigDate, intDateInterval, kSyncFlag, kStartTime]; 
    if(sqlite3_prepare_v2(_database,[query UTF8String],-1,&statement,NULL)==SQLITE_OK) 
    { 
     while (sqlite3_step(statement)<=SQLITE_ROW) 
     { 
      dic = [NSMutableDictionary dictionary]; 

      float dbDataAsDouble0 = sqlite3_column_double(statement, 0); 
      NSDate *dateRetrieved = [NSDate dateWithTimeIntervalSince1970:dbDataAsDouble0]; 
      NSString *strDate = [[StaticHelper sharedObject] getStringFromDate:dateRetrieved]; 
      //char *dbDataAsChars0 = (char*)sqlite3_column_text(statement, 0); 

      if (strDate != nil) 
       [dic setObject:strDate forKey:kGigDate]; 
      else{ 
       [dic setObject:@"" forKey:kGigDate]; 
      } 


      char *dbDataAsChars1 = (char*)sqlite3_column_text(statement, 1); 
      if (dbDataAsChars1 != NULL) 
       [dic setObject:[NSString stringWithUTF8String:dbDataAsChars1] forKey:kStartTime]; 
      else{ 
       [dic setObject:@"" forKey:kStartTime]; 
      } 


      char *dbDataAsChars2 = (char*)sqlite3_column_text(statement, 2); 
      if (dbDataAsChars2 != NULL) 
       [dic setObject:[NSString stringWithUTF8String:dbDataAsChars2] forKey:kDoorsOpen]; 
      else{ 
       [dic setObject:@"" forKey:kDoorsOpen]; 
      } 


      char *dbDataAsChars3 = (char*)sqlite3_column_text(statement, 3); 
      if (dbDataAsChars3 != NULL) 
       [dic setObject:[NSString stringWithUTF8String:dbDataAsChars3] forKey:kEndTime]; 
      else{ 
       [dic setObject:@"" forKey:kEndTime]; 
      } 


      char *dbDataAsChars4 = (char*)sqlite3_column_text(statement, 4); 
      if (dbDataAsChars4 != NULL) 
       [dic setObject:[NSString stringWithUTF8String:dbDataAsChars4] forKey:kGigTitle]; 
      else{ 
       [dic setObject:@"" forKey:kGigTitle]; 
      } 


      char *dbDataAsChars5 = (char*)sqlite3_column_text(statement, 5); 
      if (dbDataAsChars5 != NULL) 
       [dic setObject:[NSString stringWithUTF8String:dbDataAsChars5] forKey:kMainArtist]; 
      else{ 
       [dic setObject:@"" forKey:kMainArtist]; 
      } 


      char *dbDataAsChars6 = (char*)sqlite3_column_text(statement, 6); 
      if (dbDataAsChars6 != NULL) 
       [dic setObject:[NSString stringWithUTF8String:dbDataAsChars6] forKey:kGigType]; 
      else{ 
       [dic setObject:@"" forKey:kGigType]; 
      } 


      char *dbDataAsChars7 = (char*)sqlite3_column_text(statement, 7); 
      if (dbDataAsChars7 != NULL) 
       [dic setObject:[NSString stringWithUTF8String:dbDataAsChars7] forKey:kPromoter]; 
      else{ 
       [dic setObject:@"" forKey:kPromoter]; 
      } 


      char *dbDataAsChars8 = (char*)sqlite3_column_text(statement, 8); 
      if (dbDataAsChars8 != NULL) 
       [dic setObject:[NSString stringWithUTF8String:dbDataAsChars8] forKey:kBandMembers]; 
      else{ 
       [dic setObject:@"" forKey:kBandMembers]; 
      } 


      char *dbDataAsChars9 = (char*)sqlite3_column_text(statement, 9); 
      if (dbDataAsChars9 != NULL) 
       [dic setObject:[NSString stringWithUTF8String:dbDataAsChars9] forKey:kVenue]; 
      else{ 
       [dic setObject:@"" forKey:kVenue]; 
      } 


      char *dbDataAsChars10 = (char*)sqlite3_column_text(statement, 10); 
      if (dbDataAsChars10 != NULL) 
       [dic setObject:[NSString stringWithUTF8String:dbDataAsChars10] forKey:kTelNo]; 
      else{ 
       [dic setObject:@"" forKey:kTelNo]; 
      } 


      char *dbDataAsChars11 = (char*)sqlite3_column_text(statement, 11); 
      if (dbDataAsChars11 != NULL) 
       [dic setObject:[NSString stringWithUTF8String:dbDataAsChars11] forKey:kPostCode]; 
      else{ 
       [dic setObject:@"" forKey:kPostCode]; 
      } 


      char *dbDataAsChars12 = (char*)sqlite3_column_text(statement, 12); 
      if (dbDataAsChars12 != NULL) 
       [dic setObject:[NSString stringWithUTF8String:dbDataAsChars12] forKey:kImgUrl]; 
      else{ 
       [dic setObject:@"" forKey:kImgUrl]; 
      } 


      char *dbDataAsChars13 = (char*)sqlite3_column_text(statement, 13); 
      if (dbDataAsChars13 != NULL) 
       [dic setObject:[NSString stringWithUTF8String:dbDataAsChars13] forKey:kTicketPrice]; 
      else{ 
       [dic setObject:@"" forKey:kTicketPrice]; 
      } 


      char *dbDataAsChars14 = (char*)sqlite3_column_text(statement, 14); 
      if (dbDataAsChars14 != NULL) 
       [dic setObject:[NSString stringWithUTF8String:dbDataAsChars14] forKey:kBookingUrl]; 
      else{ 
       [dic setObject:@"" forKey:kBookingUrl]; 
      } 


      char *dbDataAsChars15 = (char*)sqlite3_column_text(statement, 15); 
      if (dbDataAsChars15 != NULL) 
       [dic setObject:[NSString stringWithUTF8String:dbDataAsChars15] forKey:kSoldOut]; 
      else{ 
       [dic setObject:@"" forKey:kSoldOut]; 
      } 


      char *dbDataAsChars16 = (char*)sqlite3_column_text(statement, 16); 
      if (dbDataAsChars16 != NULL) 
       [dic setObject:[NSString stringWithUTF8String:dbDataAsChars16] forKey:kVenueUrl]; 
      else{ 
       [dic setObject:@"" forKey:kVenueUrl]; 
      } 


      char *dbDataAsChars17 = (char*)sqlite3_column_text(statement, 17); 
      if (dbDataAsChars17 != NULL) 
       [dic setObject:[NSString stringWithUTF8String:dbDataAsChars17] forKey:kVenueBlog]; 
      else{ 
       [dic setObject:@"" forKey:kVenueBlog]; 
      } 


      [queryResult addObject:dic]; 

     } 
     sqlite3_finalize(statement); 

    } 
    else{ 
     ////NSLog(@"Error msg : %s ", sqlite3_errmsg(_database)); 
     return nil; 

    } 
    sqlite3_close(_database); 
} 
else{ 
    NSLog(@"database not open : %s",sqlite3_errmsg(_database)); 
} 
return queryResult; 

}

ответ

1

Если база данных уже открыта и заблокирована с какой-нить -процесса, она дает эту ошибку при попытке открыть его (Попробуйте открыть запертую базу данных)

В вас getDataFromTable_VENUES_WhereGigDateIsEqualTo метод, Проверьте следующее:

else{ 
      ////NSLog(@"Error msg : %s ", sqlite3_errmsg(_database)); 
     return nil; 

    } 

здесь вы returing без разблокировки открытой базы данных с

sqlite3_close(_database); 

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

 else{ 
        sqlite3_close(_database); 
    ////NSLog(@"Error msg : %s ", sqlite3_errmsg(_database)); 
      return nil; 

     } 

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

#import <Foundation/Foundation.h> 
#import <sqlite3.h> 

@interface DBManager : NSObject 
{ 
    NSString *databasePath; 
} 

+(DBManager*)getSharedInstance; 
@end 


#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 openDB]; 
    } 
    return sharedInstance; 
} 

-(BOOL)openDB{ 

// Код, чтобы открыть базу данных, присвоить что database, вернуть статус

 } 
+0

Как вы сказали об удалении комментария от линии я получаю «базы данных заблокирована» ошибки. Кроме того, у меня есть класс singleton для базы данных, но я не могу понять, что если я открою базу данных один раз в методе getSharedInstance, где мне нужно ее закрыть. – mars

+0

Вы можете закрыть базу данных по методу dealloc. – Darshana

+1

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

1

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

- (void) openDatabaseConnection 
{ 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    path = [documentsDirectory stringByAppendingPathComponent:yourDB]; 

    if (sqlite3_open_v2([path UTF8String], &databaseName, SQLITE_OPEN_READWRITE, NULL) == SQLITE_OK) 
    { 
     NSLog(@"Data base connection opened %@",path); 
    } 
    else 
    { 
     NSLog(@"Error in opening database :("); 
    } 
} 

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