Przykład lub Wyjaśnienie migracji danych podstawowych z wieloma przebiegami?

Moja aplikacja na iPhone ' a musi przenieść swój podstawowy magazyn danych, a niektóre bazy danych są dość duże. Dokumentacja Apple sugeruje użycie" wielu przejść " do migracji danych w celu zmniejszenia zużycia pamięci. jednak dokumentacja jest bardzo ograniczona i nie wyjaśnia zbyt dobrze, jak to zrobić. Czy ktoś może wskazać mi jakiś dobry przykład, albo szczegółowo wyjaśnić, jak właściwie to zrobić?

Author: Cœur, 2011-05-13

3 answers

Rozgryzłem, co Apple podpowiada w ich dokumentacji. To naprawdę bardzo proste, ale długa droga, zanim będzie to oczywiste. Wyjaśnię to na przykładzie. Sytuacja wyjściowa jest następująca:

Model Danych Wersja 1

Tutaj wpisz opis obrazkaTutaj wpisz opis obrazka

Jest to model, który otrzymujesz podczas tworzenia projektu za pomocą szablonu "aplikacja oparta na nawigacji z podstawowym przechowywaniem danych". Skompilowałem go i zrobiłem kilka mocnych uderzeń z pomocą pętli for, aby stworzyć wokół 2K wpisy wszystkie z różnymi wartościami. No i mamy 2.000 zdarzeń z wartością NSDate.

Teraz dodajemy drugą wersję modelu danych, która wygląda tak:

Tutaj wpisz opis obrazka

Model Danych Wersja 2

Różnica polega na tym, że jednostka Eventowa zniknęła, a my mamy dwie nowe. Jeden, który przechowuje znacznik czasu jako double, a drugi, który powinien przechowywać datę jako NSString.

Celem jest przeniesienie wszystkich Wersja 1 zdarzeń do dwóch nowych encje i konwertować wartości wzdłuż migracji. Powoduje to dwukrotność wartości każdego z nich jako innego typu w osobnym obiekcie.

Aby migrować, wybieramy migrację ręcznie i robimy to z modelami mapowania. Jest to również pierwsza część odpowiedzi na twoje pytanie. Migrację wykonamy w dwóch krokach, ponieważ migracja wpisów 2k zajmuje dużo czasu i chcemy, aby pamięć była niska.

Można nawet dalej podzielić te modele mapowania na migruj tylko zakresy jednostek. Powiedzmy, że mamy milion płyt, to może zakończyć cały proces. Można zawęzić pobrane elementy za pomocą predykatu filtra .

Wróćmy do naszych dwóch modeli mapowania.

Tworzymy pierwszy model mapowania w następujący sposób:

1. Nowy Plik -> Zasób - > Model Mapowania Tutaj wpisz opis obrazka

2. Wybierz nazwę, wybrałem StepOne

3. Ustaw dane źródłowe i docelowe model

Tutaj wpisz opis obrazka

Model Mapowania Krok Pierwszy

Tutaj wpisz opis obrazka

Tutaj wpisz opis obrazka

Tutaj wpisz opis obrazka

Migracja wieloprzebiegowa nie wymaga niestandardowych zasad migracji jednostek, jednak zrobimy to, aby uzyskać więcej szczegółów w tym przykładzie. Dodajemy więc niestandardową Politykę do jednostki. Jest to zawsze podklasa NSEntityMigrationPolicy.

Tutaj wpisz opis obrazka

Ta klasa polityki implementuje kilka metod, aby nasza migracja się odbyła. Jednak jest to proste w w tym przypadku będziemy musieli wdrożyć tylko jedną metodę: createDestinationInstancesForSourceInstance:entityMapping:manager:error:.

Implementacja będzie wyglądała tak:

Krok po krokum

#import "StepOneEntityMigrationPolicy.h"


@implementation StepOneEntityMigrationPolicy

- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance 
                                      entityMapping:(NSEntityMapping *)mapping 
                                            manager:(NSMigrationManager *)manager 
                                              error:(NSError **)error
{
    // Create a new object for the model context
    NSManagedObject *newObject = 
        [NSEntityDescription insertNewObjectForEntityForName:[mapping destinationEntityName] 
                                      inManagedObjectContext:[manager destinationContext]];

    // do our transfer of nsdate to nsstring
    NSDate *date = [sInstance valueForKey:@"timeStamp"];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
    [dateFormatter setDateStyle:NSDateFormatterMediumStyle];    

    // set the value for our new object
    [newObject setValue:[dateFormatter stringFromDate:date] forKey:@"printedDate"];
    [dateFormatter release];

    // do the coupling of old and new
    [manager associateSourceInstance:sInstance withDestinationInstance:newObject forEntityMapping:mapping];

    return YES;
}

Ostatni krok: sama migracja

Pominę część do Ustawienia drugiego modelu mapowania, który jest prawie identyczny, tylko timeIntervalSince1970 używany do konwersji NSDate na podwójne.

W końcu musimy uruchomić migrację. Na razie pominę kod do kotła. Jeśli potrzebuję go, napiszę tutaj. Można go znaleźć w dostosowywanie procesu migracji to tylko połączenie dwóch pierwszych przykładów kodu. Trzecia i ostatnia część zostanie zmodyfikowana w następujący sposób: zamiast używać metody klasowej NSMappingModel Klasa mappingModelFromBundles:forSourceModel:destinationModel: użyjemy initWithContentsOfURL: ponieważ metoda class zwróci tylko jeden, być może pierwszy, znaleziony model mapowania w pakiecie.

Teraz mamy dwa modele mapowania, które mogą być używane w każdym przejściu zapętl i wyślij metodę migrate do Menedżera migracji. To wszystko.

NSArray *mappingModelNames = [NSArray arrayWithObjects:@"StepOne", @"StepTwo", nil];
NSDictionary *sourceStoreOptions = nil;

NSURL *destinationStoreURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreDataMigrationNew.sqlite"];

NSString *destinationStoreType = NSSQLiteStoreType;

NSDictionary *destinationStoreOptions = nil;

for (NSString *mappingModelName in mappingModelNames) {
    NSURL *fileURL = [[NSBundle mainBundle] URLForResource:mappingModelName withExtension:@"cdm"];

    NSMappingModel *mappingModel = [[NSMappingModel alloc] initWithContentsOfURL:fileURL];

    BOOL ok = [migrationManager migrateStoreFromURL:sourceStoreURL
                                               type:sourceStoreType
                                            options:sourceStoreOptions
                                   withMappingModel:mappingModel
                                   toDestinationURL:destinationStoreURL
                                    destinationType:destinationStoreType
                                 destinationOptions:destinationStoreOptions
                                              error:&error2];
    [mappingModel release];
} 

Uwagi

  • Model mapowania kończy się cdm w pakiecie.

  • Sklep docelowy musi być dostarczony, a nie powinien być sklepem źródłowym. Możesz po udanej migracji usunąć stary i zmienić nazwę nowego.

  • Zrobiłem kilka zmian w modelu danych po utworzeniu modeli mapowania, spowodowało to pewną kompatybilność błędy, które mogłem rozwiązać tylko poprzez odtworzenie modeli mapowania.

 175
Author: Nick Weaver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-05-18 04:00:28

Te pytania są powiązane:

Problemy z pamięcią migracja dużych magazynów danych CoreData na iPhone

Migracja wielu rdzeni w kawałkach z systemem iOS

Zacytuję pierwszy link:

Jest to omówione w oficjalnym dokumentacja w zakładce " wielokrotne przejścia" sekcji, jednak wygląda na to, że ich sugerowanym podejściem jest podział twoja migracja według typu encji, np. tworzyć wiele modeli mapowania, każdy z które migrują a podzbiór podmiotu typy z pełnego modelu danych.

 3
Author: occulus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:35

Załóżmy, że twój schemat bazy danych zawiera 5 encji, np. person, student, course, class i registration, aby użyć standardowego przykładu, w którym podklasa student person, class implementuje kurs, a rejestracja łączy klasę i studenta. Jeśli wprowadziłeś zmiany we wszystkich definicjach tabel, musisz zacząć od klas bazowych i iść w górę. Nie możesz więc zacząć od konwersji rejestracji, ponieważ każdy rekord rejestracji zależy od posiadania tam klasy i uczniów. Więc ty rozpocznie się od migracji tylko tabeli Person, skopiowania istniejących wierszy do nowej tabeli i wypełnienia dowolnych nowych pól (jeśli to możliwe) i odrzucenia usuniętych kolumn. Wykonaj każdą migrację wewnątrz puli autorelease, aby po jej zakończeniu pamięć wróciła do początku.

Po zakończeniu tabeli osób, możesz przekonwertować tabelę uczniów. Następnie przeskocz do kursu, a następnie klasy, a na koniec tabela rejestracyjna.

Druga uwaga to liczba rekordów, gdyby taka osoba miała tysiąc wierszy, musiałbyś, co około 100, wykonać odpowiednik nsmanagedobject z wydania, który polega na określeniu kontekstu zarządzanego obiektu [moc refreshObject:ob mergeChanges: NO]; Ustaw również swój timer nieświeżych danych na niskim poziomie, aby pamięć była często spłukiwana.

 -5
Author: PapaSmurf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-21 03:02:37