2010-03-01 2 views
10

내 응용 프로그램에서 때로는 데이터베이스 파일을 다시 작성하고 다시 채워야합니다. SQLite databse는 CoreData 스택에 의해 생성되고 관리됩니다.coredata가 sqlite 데이터베이스 모델을 다시 작성하도록 강제하는 방법은 무엇입니까?

내가하려는 것은 파일을 삭제 한 다음 persistentStoreCoordinator 객체를 다시 생성하는 것입니다.

그것은 시뮬레이터에서 작동하지만 나는 그런 오류를 받고 있어요 장치에 :

NSFilePath = "/var/mobile/Applications/936C6CC7-423A-46F4-ADC0-7184EAB0CADD/Documents/MYDB.sqlite"; 
NSUnderlyingException = I/O error for database at /var/mobile/Applications/936C6CC7-423A-46F4-ADC0-7184EAB0CADD/Documents/MYDB.sqlite. SQLite error code:1, 'table ZXXXX already exists'; 

나는 어떤 식 으로든이의 원인을 찾을 수 없습니다. 두 가지 다른 문제를 나타냅니다 - 코코아 오류 256은 파일이 없거나 읽을 수 없음을 나타냅니다. 그러나 파일이 비어 있더라도 persistentStoreCoordinator를 생성 한 후 파일이 생성되지만 일부 쿼리를 실행 한 후에 사라집니다.

alredy 기존 테이블을 만들려고 시도하는 것을 나타내는 두 번째 메시지는이 경우 매우 이상합니다.

나는 꽤 혼란스럽고 여기서 무슨 일이 일어나는지 알 수 없다. 내 코드는 다음과 같습니다.

NSString *path = [[WLLocalService dataStorePath] relativePath]; 
NSError *error = nil; 

WLLOG(@"About to remove file %@", path); 

[[NSFileManager defaultManager] removeItemAtPath: path error: &error]; 

if (error != nil) { 
WLLOG(@"Error removing the DB: %@", error); 
} 


[self persistentStoreCoordinator]; 

WLLOG(@"Rebuild DB result %d", [[NSFileManager defaultManager] fileExistsAtPath: path]); 

이 코드를 실행 한 후에는 DB 파일이 있지만 비어 있습니다. 첫 번째 쿼리 (및 이후의 모든 쿼리)가 실행되면 위의 오류가 발생하고 파일이 사라집니다.

누구에게 잘못된 점이 있습니까?

올바른 방법을 알려 주셔서 대단히 감사합니다!

답변

18

가 핵심 데이터 스택은 당신이 아래의 파일을 제거 좋아하지 않는다 :

는 여기에 몇 가지 (이 버전을 통해 기존 DB를 복사하지 않습니다하지만) 비슷한 않는 응용 프로그램의 코드입니다. 파일을 삭제하려면 스택을 분리해야하며 파일을 삭제 한 다음 스택을 재구성하십시오. 그러면 문제가 해결됩니다.

문제의 일부는 스택에 파일의 데이터 캐시를 유지한다는 것입니다. 파일을 제거 할 때 캐시를 삭제할 방법이 없으므로 코어 데이터를 알 수없고 불안정한 상태로 둡니다. 당신은 NSPersistentStoreCoordinator 당신이 -removePersistentStore:error:를 호출하여 파일을 제거하고 -addPersistentStoreWithType:configuration:URL:options:error:에 대한 호출로 새로운 저장소를 추가하는 말 시도 할 수 있습니다

. 현재 ZSync에서 그 일을하고 있으며 잘 작동합니다.

+0

팁 주셔서 감사합니다. 흥미 롭습니다. 시도해 보겠습니다.그러나 NSPersistentStoreCoordinator의 모든 인스턴스가 파일이 제거되기 직전에 해제 될 때 동일하지 않습니까? 그것은 위의 메서드를 호출하기 바로 전에 발생합니다. 나는 모든 후속 데이터 구조를 제거하고 해제한다고 가정합니다. 파일 자체를 제거하기 전에 코디네이터에서 영구 저장소를 명시 적으로 제거하는 것이 중요한 이유를 설명 할 수 있습니까? – Burt

+0

그래서 당신의 솔루션을 시도하고 그것을 작동합니다! 그 점에 큰 감사드립니다! 그러나 나는 아직도 영구 저장소를 제거하고 단순히 코디네이터를 해제하는 것의 차이점을 궁금해합니다. – Burt

+1

'NSManagedObjectContext'에서'NSPersistentStoreCoordinator'를 nil로 설정하고 해제하면 동일한 작업을 수행 할 수는 있지만 단순히 'NSPersistentStoreCoordinator'에 저장소 삭제를 지시하는 것보다 훨씬 무거울 수 있습니다. –

1

sqlite 데이터베이스의 복사본을 응용 프로그램 번들의 일부로 유지 한 다음 데이터베이스를 새로 고칠 때마다 문서 디렉토리의 해당 버전을 복사 할 수 있습니다.

// Check for the existence of the seed database 
// Get the path to the documents directory and append the databaseName 
NSString* databasePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: kDatabaseName]; 

NSFileManager* fileManager = [NSFileManager defaultManager]; 
if (![fileManager fileExistsAtPath: databasePath]) 
{ 
    NSString* databasePathFromApp = [[[NSBundle mainBundle] resourcePath] 
            stringByAppendingPathComponent: kDatabaseName]; 

    [fileManager copyItemAtPath: databasePathFromApp 
         toPath: databasePath 
          error: nil]; 
} 
[fileManager release]; 
8

-resetApplicationModel은 내 응용 프로그램 대리인에서 사용하며 제대로 작동합니다.

당신은 kApplicationIsFirstTimeRunKey 사용자 기본이 필요하지 않을 수 있습니다,하지만 난 처음 실행 플래그가 있다면 나 또한 -applicationDidFinishLaunching:에서 호출 -setupModelDefaults라는 사용자 지정 방법에 기본 설정으로 코어 데이터 저장소를 채울 수 있는지 여부를 테스트하는 데 사용할 YES.

- (BOOL) resetApplicationModel { 

    // ---------------------- 
    // This method removes all traces of the Core Data store and then resets the application defaults 
    // ---------------------- 

    [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:YES] forKey:kApplicationIsFirstTimeRunKey]; 
    NSLog(@"Turned ON the first-time run flag..."); 

    NSError *_error = nil; 
    NSURL *_storeURL = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"MyAppSQLStore.sqlite"]]; 
    NSPersistentStore *_store = [persistentStoreCoordinator persistentStoreForURL:_storeURL]; 

    // 
    // Remove the SQL store and the file associated with it 
    // 
    if ([persistentStoreCoordinator removePersistentStore:_store error:&_error]) { 
     [[NSFileManager defaultManager] removeItemAtPath:_storeURL.path error:&_error]; 
    } 

    if (_error) { 
     NSLog(@"Failed to remove persistent store: %@", [_error localizedDescription]); 
     NSArray *_detailedErrors = [[_error userInfo] objectForKey:NSDetailedErrorsKey]; 
     if (_detailedErrors != nil && [_detailedErrors count] > 0) { 
      for (NSError *_detailedError in _detailedErrors) { 
       NSLog(@" DetailedError: %@", [_detailedError userInfo]); 
      }     
     } 
     else { 
      NSLog(@" %@", [_error userInfo]); 
     } 
     return NO; 
    } 

    [persistentStoreCoordinator release], persistentStoreCoordinator = nil; 
    [managedObjectContext release], managedObjectContext = nil; 

    // 
    // Rebuild the application's managed object context 
    // 
    [self managedObjectContext]; 

    // 
    // Repopulate Core Data defaults 
    // 
    [self setupModelDefaults]; 

    return YES; 
} 
+0

안녕하세요 @ 알렉스 레이놀즈, 난 내 coreData에있는 모든 데이터를 재설정하고 싶습니다, 내가 알고 싶은, 무엇 [setupModeDefaults] 기능을합니까.? 또한 이것 좀 봐주세요 http://stackoverflow.com/questions/14646595/ how-to-clear-reset-all-coredata-in-one-to-many-realationship – Ranjit

+0

코어 데이터 저장소를 기본값으로 다시 채우는 방법 일뿐입니다. 자신 만의 메서드를 작성하여 기본값으로 되돌릴 수 있습니다. –

+0

응답 해 주셔서 감사합니다. 코드를 사용해 보았지만 작동하지 않습니다. 나를 도와주세요. – Ranjit

관련 문제