2013-02-23 13 views
5

Po dodaniu nowej wersji modelu Core Data do mojej aplikacji wykonałem niewielką migrację, najwyraźniej z powodzeniem. Zmigrowany plik jest ładowany poprawnie, ale przy pierwszej próbie uzyskania dostępu do atrybutu za pośrednictwem określonej relacji aplikacja ulega awarii z wartością NSRangeException: '*** -[__NSArrayM objectAtIndex:]: index 4294967295 beyond bounds [0 .. 35]'. Ta relacja działała dobrze przed migracją. Wiem z innych postów, że 4294967295 jest naprawdę -1, ale jedyną rzeczą, którą mogę zidentyfikować w 36 elementach w mojej aplikacji/danych jest to, że w modelu danych jest 36 całych obiektów (dla odniesienia, pobrana relacja ma 58 pozycji w jego tabeli).NSRangeException po migracji danych podstawowych

Pytanie:

Moje pytanie brzmi: na podstawie błędu dostaję i rozwiązywania problemów robiłem poniżej, istnieje rodzaj zmiany schematu, który mógłby przejść lekką migracji, ale uszkodzony dane po drodze, prowadzące do wspomnianego wyjątku? Spróbuję podzielić migrację na mniejsze fragmenty w kilku wersjach, aby wyizolować lub ominąć problem, ale byłoby miło móc skupić się na konkretnych zmianach schematu, które mogą być wadliwe.

Niepowodzenie:

Niepowodzenie występuje z następującego kodu w "MyObject":

[[self object2] text]; 

Relacja object2 jest jeden, non-opcjonalne oba sposoby i ani do przodu, ani odwrotna zależność została zmieniona między modelami danych. Atrybut text prawdopodobnie nie ma znaczenia, ponieważ gdy wystąpi błąd, w obiekcie2 nie zostanie osiągnięty awakeFromFetch. Jeśli przypiszę [self object2] do zmiennej przed powyższą instrukcją, przypisanie zakończy się powodzeniem i zgłasza data: <fault>.

Baza:

Patrząc na bazie danych w sqlite3, zauważam następujące:

  1. wartości indeksu dla przednich i odwrotnych relacji wydaje się być prawidłowa w każdej tabeli.
  2. Tabela object2 ma dwie kolumny dla relacji odwrotnej zamiast poprzedniej, a dodatkową Z2_MYOBJECT, która jest pusta dla wszystkich wierszy. Żadna inna relacja nie została dodana w celu wyjaśnienia tej kolumny.
  3. W tabeli wszystkie wpisy po migracji pokazują -1 dla , podczas gdy przed migracją pokazywały zero dla pustych tabel i maksymalny numer wiersza dla wypełnionych tabel. Ręczne aktualizowanie do odpowiednich wartości Z_MAX nie pomogło w przypadku wyjątku. Wszystkie wartości Z_SUPER były poprawne.

Ustawiłem model odwzorowania, aby sprawdzić, czy coś nie wyglądało dobrze z automatycznym odwzorowaniem, ale wszystko wyglądało dobrze.

Ogólny schemat zmienia:

W wersji źródłowej modelu danych, było czternaście podmiotów, z których tylko cztery zostały wypełnione danymi (aplikacja jest wciąż w rozwoju). Siedem było jednostkami najwyższego poziomu, a siedem było podelementami trzech jednostek najwyższego poziomu.

W docelowej wersji modelu danych dodano dwadzieścia dwa podmioty, niektóre najwyższego poziomu i niektóre podjednostki, z dziesiątkami relacji, w tym niektóre dodane do istniejących podmiotów.

Niektóre atrybuty i relacje zostały usunięte z istniejących obiektów, a inne zostały dodane. Żadne typy danych ani ustawienia relacji nie zostały zmienione, nie zmieniono atrybutów ani relacji i nie były wymagane żadne specjalne odwzorowania.

Aktualizacja (2/25/12): Kiedy zacząłem pracować nad nowym modelem pośrednim, przypomniałem sobie, że zmieniłem klasę (representClassName) dla wielu jednostek z NSManagedObject na podklasę NSManagedObject, ale nie wygenerował pliki klas. Nie podejrzewałem, że może to spowodować problem i rzeczywiście tworzenie wszystkich plików klas nie pomogło w przypadku wyjątku. Chciałem tylko zauważyć, że to kolejna zmiana między modelami.

Wnioski:

Jest to dzikie przypuszczenie, ale jeśli liczba 36 Jednostka nie jest przypadkiem, wydaje się, że gdy „MyObject” próbuje się przyczepić w „object2” nie posiada ważnego odniesienia dla tabeli i próbuje załadować tabelę o wartości -1, powodując wyjątek. Fakt, że proste zadanie [self object2] zakończyło się powodzeniem, nie jest jednak zgodny z tym wnioskiem.

Wszelkie pomysły?

Odpowiedz

2

Dokonując kilku migracji przyrostowych, udało mi się ustalić przyczynę problemu i rozwiązać problem.

Problem:

Jednym z istniejących podmiotów z danymi nie ma jednostek podrzędnych w bieżącym modelu. Jeśli utworzę nowy model, który po prostu doda element podrzędny, nie zawierający żadnych atrybutów ani relacji, i nie wprowadzi żadnych innych zmian, wystąpi wyjątek NSRangeException, Z_MAX i podwojenie relacji odwrotnej odnotowane w moim pytaniu.

Rozwiązanie:

po stwierdzeniu niepowodzenia w wyniku „lekkiej” pomyślnego migracji w powyższym przypadku, utworzonego model odwzorowania. Ponieważ jedyną zmianą była jedna dodatkowa jednostka, wszystkie z wyjątkiem jednego mapowania encji były proste. Pytanie brzmiało, co zrobić z pojedynczym dodanym bytem.

Domyślnie dodana jednostka bez własnych atrybutów lub relacji pokazywała odwzorowania atrybutów i relacji dla wszystkich właściwości rodzica. Wszystkie odwzorowania miały domyślnie puste wyrażenia wartości, co zakładałem, że po prostu pominie je podczas migracji. To nieprawda, najwyraźniej. Usuwając wszystkie odwzorowania atrybutów i relacji w odwzorowaniu jednostek, a następnie wyłączając wnioskowane mapowanie, migracja przebiegła pomyślnie.

Nadal mam do czynienia z wszystkimi pozostałymi podmiotami i będę próbować tego podejścia, aby zrobić resztę zbiorczo, z niezmienionymi wszystkimi planowanymi atrybutami i relacjami.

+0

w jaki sposób został wybrany model mapowania? po wyłączeniu automatycznej migracji? –

+0

@ JoãoNunes Po wyłączeniu automatycznej migracji powinien automatycznie wybrać model odwzorowania, o ile pasują do niego wartości źródłowe i docelowe. Powinny się one zgadzać, o ile nie zmodyfikowałeś modelu danych od czasu utworzenia modelu odwzorowania. Niestety, czasami nie, jak to tutaj zaznaczono: (http://stackoverflow.com/questions/10894383/core-data-mapping-model-version-hashes-not-matching-to-source-model-version-hash). Włączenie trybu debugowania podstawowych danych może pomóc w rozwiązywaniu problemów z brakiem wyboru modeli odwzorowania. –

+0

Dzięki za cynk. Dodałem debugowanie dla migracji, ale nadal mam problem. Stworzyłem tutaj pytanie: http://stackoverflow.com/questions/17464414/core-data-mapping-model-not-working- with-correct-hashes –

1

Twoje posty były pomocne, gdy napotkałem ten problem. Dziękuję Ci. [Czy zgłosiłeś już błąd?]

Oto kilka bardziej eksperymentalnych wyników, ale, niestety, nie jest to świetne rozwiązanie.

  • Moja zmiana schematu podobnie dodał podtyp podmiot, który nie ma dodatkowych atrybutów lub relacje. Komunikat o błędzie jest taki sam jak twój, z wyjątkiem ograniczeń: [0 .. 19]. Odpowiada to 20 rodzajom jednostek, potwierdzając twoją hipotezę. Podobnie jak w Twojej sytuacji błąd wystąpił podczas próby uzyskania dostępu do właściwości encji po zakończeniu migracji.

  • Dodanie atrapowego atrybutu i atrapa relacja własna do nowego typu jednostki nie pozwoliło uniknąć awarii po migracji. (Jednak nie testowałem z tym nowym rodzajem jednostki jako zmianę tylko schematu odkąd poprzednio pchnął tę zmianę schematu do alfa testerów.)

  • I obserwować objawy Z2_MYOBJECT kolumn i Z_PRIMARYKEY.Z_MAX = -1 po udanych migracje dla innych zmiany schematu, więc nie muszą wcale być problematyczne. Wartości -1 są leniwie zastępowane odpowiednimi wartościami maksymalnymi. Dodatkowa kolumna może być używana podczas migracji.

  • W moim przypadku nadmiarowość nowej jednostki ma uporządkowaną relację wiele do wielu. W bardzo prostym przypadku, gdy cała składnica danych zawiera tylko jedną instancję obiektu (instancję tego typu obiektu bez linków do relacji wychodzących), migracja schematu powiedzie się. Ma dodatkowe kolumny Z2_MYOBJECT i wartości, a wynikowy magazyn danych działa poprawnie podczas dodawania obiektów z tego miejsca.

  • Próbowałem utworzyć model odwzorowania, ale nie udało się uzyskać danych podstawowych, aby go zastosować. Wyłączenie wnioskowania o mapowaniu spowodowało, że dane podstawowe nie mogły w ogóle migrować. Czy istnieje podstęp? Czy muszę napisać niestandardowy kod migracji, aby wywołać model mapowania? To jest Xcode 4.6.2, więc starszy błąd już dawno minął.

  • Podczas używania git toczyć model danych Kod & tyłu lub do przodu, aby przeprowadzić eksperyment, wydaje się konieczne (1) blisko & ponownym otwarciu projektu Xcode i (2) wykonać czystą kompilację. W przeciwnym razie Xcode może ulec awarii i/lub pozostawić stan zakłócający.

  • Aby eksperymentalnie toczyć do tyłu, należy usunąć katalog .momd/ lub całą aplikację z docelowym symulatorze iOS/urządzenia (lub wdrożyć aplikację za pośrednictwem iTunes lub TestFlight) od przesunięcia poprzez Xcode nie usunie zbędne pliki (jak .mom i .omo definicje modeli danych), co z kolei pozwala aplikacji wykonywać lekkie migracje, których nie może wykonać rzeczywista wdrożona aplikacja.

  • Informacje na temat mapowania jednostki do użycia dla dodanego typu jednostki wskazują, że gdy Core Data stosuje model odwzorowania, kopiuje elementy ze starej składnicy danych do nowej. To nie modyfikuje tabel w miejscu. Nie chcesz go "pomijać" właściwości (w tym dziedziczone właściwości), chyba że chcesz je upuścić.

  • Ponieważ jednak zmiana schematu dodała typ jednostki, to jednostka nie ma żadnych instancji do migracji, więc jej niestandardowe reguły modelu odwzorowania nie mają znaczenia.

Dlatego zastanawiam się, czy coś innego spowodowało swoje wywala się zatrzymać, jak resztki eksperymentalnych .mom plików lub kodu niestandardowego migracji. Czy Twoje obejście się zatrzymało?

Po 2 dniach eksperymentowania zdecydowałem, że testerzy alfa będą musieli tym razem żyć bez migracji danych. Na szczęście stało się tak bez klientów produkcyjnych. Ale nie daje mi to zaufania do danych podstawowych.

+0

Dziękujemy za Twoje dodatkowe informacje. Po przejściu obok opisywanej tutaj kwestii, według mojej odpowiedzi, natknąłem się na inny powracający problem, który zajmował moją uwagę: (http: // stackoverflow.com/questions/10894383/core-data-mapping-model-version-hashes-niezgodny-do-źródła-model-wersja-hash). Odpowiedź udzielona na to pytanie nie rozwiązała problemu, więc dodałem do niego nagrodę, ale nie otrzymałem odpowiedzi. Nie zgłosiłem tego błędu, ponieważ miałem nadzieję wziąć udział w sesji Core Data na lokalnej konferencji Cocoa w zeszłym miesiącu i sprawdzić, czy eksperci znali rozwiązanie. Niestety nie mogłem uczestniczyć. –

+0

Ogólnie nie trzeba pisać niestandardowego kodu migracji, jednak jest kilka rzeczy, które mogą uniemożliwić działanie modelu odwzorowania. Jedna z nich została omówiona w pytaniu, które zawierałem w powyższym komentarzu. Będziesz chciał sprawdzić skróty w modelu odwzorowania w porównaniu do pliku źródłowego i aktywnej wersji modelu. Sprawdź odpowiedź na to pytanie, aby uzyskać szczegółowe informacje na temat debugowania Core Data, jeśli jeszcze tego nie zrobiłeś: http://stackoverflow.com/questions/12835950/debug-core-data-migration-to-compare-hash-values –

1

Po dodaniu modelu podstawowego modelu danych podczas uzyskiwania dostępu do dowolnego wystąpienia konkretnej jednostki po automatycznej migracji lekkiej miałem taki sam rodzaj NSRangeException. W moim przypadku również zakres odpowiadał liczbie obiektów w moim modelu.

Wygenerowałem model odwzorowania z Xcode 4.6 (4H127) przy użyciu File > New > File..., a następnie wybierając Core Data > Mapping Model. To spowodowało krach do (d) przekształci się -[NSSymbolicExpression length]: unrecognized selector sent to instance...

Rozwiązanie

Problem w moim przypadku było to, że moja jednostka przyczyną pierwotną katastrofę miał związek o nazwie size, które jest słowem zarezerwowanym wymienione w Apple Predicate Programming Guide . Badanie modelu mapowania ujawniły, że zarezerwowane słowo zostało aktywowane w wyrażeniu wartość dla relacji:

FUNCTION($manager, "destinationInstancesForEntityMappingNamed:sourceInstances:" , "PNSizeOptionToPNSizeOption", $source.SIZE)

znalazłem rozwiązanie w Core Data Model Versioning and Data Migration Programming Guide:

Reserved słowa w wyrażeniach wartość niestandardową : Jeśli używasz niestandardowego wyrażenia o wartości , musisz pominąć słowa zastrzeżone, takie jak ROZMIAR, PIERWSZY i OSTATNIO używająC# (na przykład, $ źródło. # Rozmiar).

Niestety, algorytm Xcode dla generowania modelu mapowania nie rozpoznaje zarezerwowane słowa i musiałem zmienić ścieżkę klucza wyrażenie w związku inspektora mapowania do $source.#size. To rozwiązało problem. Zakładam, że wnioskowany model mapowania danych podstawowych napotkał podobny problem podczas migracji lekkiej.

Mogą być inne przyczyny tego rodzaju awarii, więc to rozwiązanie może nie mieć zastosowania, ale może warto sprawdzić nazwy właściwości w modelu na liście zarezerwowanych słów w Predicate Programming Guide.

Powiązane problemy