2014-04-15 12 views
7

Mam podstawową aplikację opartą na danych, która używa Dropbox do tworzenia kopii zapasowych i przywracania danych. Sposób tworzenia kopii zapasowych jest dość prosty. Kopiuję plik .sqlite w dropboxie użytkownika.Tworzenie kopii zapasowej .sqlite (dane podstawowe)

Teraz moja funkcja tworzenia kopii zapasowych i przywracania działa poprawnie. Problem dotyczy samego pliku .sqlite. Wygląda na to, że plik .sqlite to niekompletny.

Wprowadziłem około 125 zgłoszeń do mojej aplikacji i wykonałem kopię zapasową. Kopia zapasowa pojawiła się w mojej skrzynce, ale kiedy używam narzędzia eksploratora .sqlite, aby zobaczyć zawartość, widzę tylko zapisy do 117. wpisu.

Próbowałem zaktualizować pierwszy wpis, a następnie ponownie obserwować plik .sqlite, ale nie wprowadzono żadnych zmian.

Co jeszcze dziwniejsze, aplikacja wydaje się rejestrować wszystkie zmiany. Po dodaniu nowego wpisu lub aktualizacji istniejącego i ponownym uruchomieniu aplikacji wydaje się, że nowo dodane dane pozostają. Ale te nowo dodane dane nie pojawiają się w moim pliku .sqlite.

mam kopii zapasowej przy użyciu tego kodu:

AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate]; 
NSString *filePath = [[[appDelegate applicationDocumentsDirectory] path] stringByAppendingPathComponent:@"MyApp.sqlite"]; 


if (account) { 
    if ([filesystem isShutDown]) { 
     filesystem = [[DBFilesystem alloc] initWithAccount:account]; 
     [DBFilesystem setSharedFilesystem:filesystem]; 
    } 

    DBPath *newPath = [[DBPath root] childPath:[NSString stringWithFormat:@"Backup - %@.sqlite", [NSDate date]]]; 
    DBFile *file = [[DBFilesystem sharedFilesystem] createFile:newPath error:nil]; 
    [file writeContentsOfFile:filePath shouldSteal:NO error:nil]; 
    [filesystem shutDown]; 

} 

ja również skopiowany plik .sqlite z folderu symulatorze i próbował widząc go w .sqlite przeglądarce. Wciąż wykazuje to samo zachowanie. Jakiś powód, dlaczego tak się dzieje?

Odpowiedz

6

Począwszy od systemu iOS 7/OS X 10.9, dane podstawowe używają "Zapisywania z wyprzedzeniem" (WAL) jako domyślnego trybu przechowywania w bazach danych SQLite jako . Jest to wyjaśnione w

Technical Q&A QA1809: New default journaling mode for Core Data SQLite stores in iOS 7 and OS X Mavericks

W trybie WAL Core danych utrzymuje główny plik sklepu nietknięty i dołącza transakcji do pliku -wal w tym samym miejscu. Po zapisaniu kontekstu danych podstawowych plik -wal nie jest usuwany, a dane w tym pliku również nie są scalane z plikiem magazynu. Dlatego po prostu robienie kopii pliku sklepu prawdopodobnie spowoduje utratę danych i niespójność .

To powinno wyjaśnić, dlaczego sam plik .sqlite jest niekompletny. jak rozwiązania można (wyjaśnione również w tej nocie technicznej):

  • Wyłącz WAL-mode (i korzystać z „stare” tryb wycofywania kroniki) dla magazynu SQLite poprzez ustawienie

    @{NSSQLitePragmasOption:@{@"journal_mode":@"DELETE"}}; 
    

    opcja podczas dodawania trwałe sklep lub

  • Użyj

    - (NSPersistentStore *)migratePersistentStore:(NSPersistentStore *)store toURL:(NSURL *)URL options:(NSDictionary *)options withType:(NSString *)storeType error:(NSError **)error 
    

    metoda tworzenia kopii zapasowej magazynu danych podstawowych.

+0

Więc co poleciłbyś? Apple zaleca drugie podejście, ale nie rozumiem, w jaki sposób mogę go użyć w Dropboxie (wygląda na dostosowany do iCloud). Jeśli teraz wyłączyłem tryb WAL, czy utracę dane już wprowadzone?A co myślisz o tworzeniu pliku zip z plikiem .sqlite i plikiem wal i zapisywaniu go jako kopii zapasowej (i odwracaniu w celu przywrócenia)? –

+0

@GauravWadhwani: W tej odpowiedzi http://stackoverflow.com/a/21002923/1187415 stwierdza się, że otwarcie sklepu za pomocą funkcji journal_mode = DELETE nie * nie * niszczy danych użytkownika, ale sam go nie przetestowałem. Drugie podejście polega na tym, że najpierw trzeba wykonać kopię zapasową do oddzielnego (pojedynczego pliku) magazynu, który następnie można przenieść do skrzynki referencyjnej (ale nie jestem zaznajomiony z funkcjami skrzynki referencyjnej). - Przepraszam, nie mogę podać ci rekomendacji. Być może inna odpowiedź przyjdzie i pomoże więcej. –

+0

Dzięki za odpowiedź. Pomógł mi rozwiązać mój problem :) –

Powiązane problemy