Czy każda Podstawowa relacja danych musi mieć odwrotność?

Powiedzmy, że mam dwie klasy encji: SocialApp i SocialAppType

W SocialApp mam jeden atrybut: appURL i jeden związek: type.

W SocialAppType mam trzy atrybuty: baseURL, name i favicon.

Miejsce przeznaczenia SocialApp relacji type jest pojedynczym zapisem w SocialAppType.

Jako przykład, dla wielu kont Flickr, byłaby liczba rekordów SocialApp, z każdym rekordem zawierającym łącze do konta danej osoby. Byłby jeden SocialAppType zapis dla typu "Flickr" , na który wskazywałyby wszystkie rekordy SocialApp.

Kiedy buduję aplikację z tym schematem, dostaję ostrzeżenie, że nie ma odwrotnej relacji między SocialAppType i SocialApp.

 /Users/username/Developer/objc/TestApp/TestApp.xcdatamodel:SocialApp.type: warning: SocialApp.type -- relationship does not have an inverse

Czy potrzebuję odwrotności i dlaczego?

Author: Alex Reynolds, 2009-04-18

8 answers

W praktyce nie miałem żadnej utraty danych z powodu braku odwrotności - przynajmniej jestem tego świadomy. Szybkie Google sugeruje, że powinieneś z nich korzystać:

Odwrotna relacja nie tylko zrobić porządek, to właściwie używany przez Core Data do przechowywania danych uczciwość.

-- Cocoa Dev Central

Powinieneś zazwyczaj modelować relacje w obu kierunkach, a określ relacje odwrotne odpowiednio. Podstawowe Dane używa tego informacje zapewniające spójność grafu obiektu, jeżeli zmiana jest wykonane (patrz " manipulowanie związkami i integralności grafu Obiektowego"). Na omówienie niektórych powodów, dla których możesz nie modelować a relacji w obu kierunkach, a niektóre z problemów, które mogą się pojawić jeśli nie, zobacz "jednokierunkowe Związki."

-- Core Data Programming Guide

 118
Author: Matthew Schinckel,
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
2018-01-29 19:55:22

Dokumentacja Apple ma świetny przykład, który sugeruje sytuację, w której możesz mieć problemy, nie mając odwrotnej relacji. Prześledźmy to do tej sprawy.

Załóżmy, że modelowałeś to następująco: Tutaj wpisz opis obrazka

Uwaga masz relację do-one o nazwie " type ", od SocialApp do SocialAppType. Relacja jest nieobowiązkowa i ma "zaprzecz" reguła delete .

Rozważ teraz, co następuje:

SocialApp *socialApp;
SocialAppType *appType;
// assume entity instances correctly instantiated

[socialApp setSocialAppType:appType];
[managedObjectContext deleteObject:appType];
BOOL saved = [managedObjectContext save:&error];

Spodziewamy się porażki ten kontekst Zapisz, ponieważ ustawiliśmy regułę delete jako Deny, podczas gdy relacja nie jest opcjonalna.

Ale tutaj uratowanie się udaje.

Powodem jest to, że nie ustawiliśmy odwrotnej relacji. Z tego powodu instancja socialApp nie jest oznaczona jako zmieniona po usunięciu appType. Tak więc nie ma walidacji dla socialApp przed zapisaniem (zakłada, że nie jest potrzebna Walidacja, ponieważ nie zaszła żadna zmiana). Ale w rzeczywistości nastąpiła zmiana. Ale nie dostaje odbicie.

Jeśli przypominamy appType przez

SocialAppType *appType = [socialApp socialAppType];

AppType jest zerowe.

Dziwne, prawda? Otrzymujemy nil za nieobowiązkowy atrybut?

Więc nie masz żadnych kłopotów, jeśli Ustawiłeś odwrotną relację. W przeciwnym razie musisz wymusić walidację, pisząc kod w następujący sposób.

SocialApp *socialApp;
SocialAppType *appType;
// assume entity instances correctly instantiated

[socialApp setSocialAppType:appType];
[managedObjectContext deleteObject:appType];

[socialApp setValue:nil forKey:@"socialAppType"]
BOOL saved = [managedObjectContext save:&error];
 139
Author: MadNik,
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
2015-07-27 21:18:05

Sparafrazuję ostateczną odpowiedź, którą znalazłem w More iPhone 3 Development autorstwa Dave ' a Marka i Jeffa LeMarche.

Firma Apple ogólnie zaleca, aby zawsze tworzyć i określać odwrotność, nawet jeśli nie używasz odwrotnej relacji w aplikacji. z tego powodu ostrzega cię, gdy nie dostarczysz odwrotności.

Relacje nie są wymagane, aby mieć odwrotność, ponieważ istnieje kilka scenariuszy, w których odwrotność relacji może zaszkodzić wydajność. Na przykład, załóżmy, że odwrotna relacja zawiera bardzo dużą liczbę obiektów. Usunięcie odwrotności wymaga iteracji nad zbiorem, który reprezentuje odwrotność, osłabiając wydajność.

Ale jeśli nie masz konkretnego powodu, aby tego nie robić, modeluj odwrotność . Pomaga w zapewnieniu integralności danych podstawowych. Jeśli napotkasz problemy z wydajnością, stosunkowo łatwo jest później usunąć odwrotną relację.

 47
Author: Rose Perrone,
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
2010-07-24 02:52:00

Lepszym pytaniem jest, "czy jest jakiś powód nie , aby mieć odwrotność"? Core Data to tak naprawdę struktura zarządzania grafami obiektowymi, a nie struktura trwałości. Innymi słowy, jego zadaniem jest zarządzanie relacjami między obiektami na wykresie obiektowym. Odwrotne relacje sprawiają, że to znacznie jest łatwiejsze. Z tego powodu Core Data oczekuje odwrotnych relacji i jest napisany dla tego przypadku użycia. Bez nich będziesz musiał samodzielnie zarządzać spójnością wykresu obiektowego. W szczególnie wiele relacji bez odwrotnej relacji jest bardzo prawdopodobne, że zostaną uszkodzone przez Podstawowe Dane, chyba że pracujesz Bardzo ciężko, aby wszystko działało. Koszt pod względem wielkości dysku dla odwrotnych relacji jest naprawdę nieznaczny w porównaniu do korzyści, jakie zyskujesz.

 24
Author: Barry Wark,
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
2009-04-21 03:53:24

Istnieje co najmniej jeden scenariusz, w którym można zrobić dobry przypadek dla podstawowej relacji danych bez odwrotności: gdy istnieje już inna podstawowa relacja danych między dwoma obiektami, która zajmie się utrzymaniem wykresu obiektów.

Na przykład książka zawiera wiele stron, podczas gdy strona jest w jednej książce. Jest to dwukierunkowy związek wielu do jednego. Usunięcie strony po prostu anuluje relację, podczas gdy usunięcie książki spowoduje również usunięcie strony.

Jednak możesz chcesz również śledzić bieżącą stronę czytaną dla każdej książki. Można to zrobić za pomocą właściwości" currentPage " na stronie , ale wtedy potrzebna jest inna logika, aby upewnić się, że tylko jedna strona w książce jest oznaczona jako bieżąca strona w dowolnym momencie. Zamiast tego, tworzenie relacji currentPage z książki do pojedynczej strony zapewni, że zawsze będzie zaznaczona tylko jedna bieżąca strona, a ponadto, że ta strona może być łatwo dostępna z odniesieniem do książki za pomocą po prostu książka.currentPage.

Graficzna prezentacja podstawowych relacji danych między książkami a stronami

Jaki byłby w tym przypadku związek wzajemny? Coś w dużej mierze bezsensownego. "myBook" lub podobny może być dodany z powrotem w innym kierunku, ale zawiera tylko informacje zawarte już w relacji "książka" dla strony, a więc stwarza własne ryzyko. Być może w przyszłości sposób korzystania z jednej z tych relacji ulegnie zmianie, co spowoduje zmiany w konfiguracji podstawowych danych. If page.myBook został użyty w niektórych miejsca, w których strona.książka powinna być używana w kodzie, mogą być problemy. Innym sposobem na proaktywne uniknięcie tego byłoby również nie eksponowanie myBook w podklasie NSManagedObject, która jest używana do uzyskania dostępu do strony. Można jednak argumentować, że łatwiej jest w pierwszej kolejności Nie modelować odwrotności.

W opisanym przykładzie reguła delete dla relacji currentPage powinna być ustawiona na "No Action" lub "Cascade", ponieważ nie ma wzajemnej relacji do"Nullify". (Kaskada oznacza, że wyrywasz każdą stronę z książki, gdy ją czytasz, ale może to być prawdą, jeśli jesteś szczególnie zimny i potrzebujesz paliwa.)

Kiedy można wykazać, że integralność grafu Obiektowego nie jest zagrożona, jak w tym przykładzie, a złożoność kodu i łatwość konserwacji są poprawione, można argumentować, że związek bez odwrotności może być prawidłową decyzją.


Alternatywnym rozwiązaniem, omówionym w komentarzach, jest utworzenie własnej właściwości UUID na obiekcie docelowym (w tym przykładzie każda strona miałaby identyfikator UUID), przechowywałaby go jako właściwość (currentPage przechowuje tylko UUID jako atrybut w książce, a nie jako relację), a następnie w razie potrzeby napisała metodę pobierania strony z pasującym UUIDEM. Jest to prawdopodobnie lepsze podejście niż używanie relacji bez odwrotności, nie tylko dlatego, że unika się omawianych komunikatów ostrzegawczych.

 21
Author: Duncan Babbage,
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
2020-08-23 21:32:24

Chociaż dokumenty nie wydają się wymagać odwrotności, po prostu rozwiązałem scenariusz, który w rzeczywistości skutkował "utratą danych", nie mając odwrotności. Mam obiekt raportujący, który ma relację do wielu na obiektach raportowalnych. Bez odwrotnej relacji, wszelkie zmiany w relacji to-many zostały utracone po ponownym uruchomieniu. Po sprawdzeniu głównego debugowania danych okazało się, że mimo zapisywania obiektu report, aktualizacje wykresu obiektu (relacji) nigdy nie były dokonywane. Dodałem odwrotność, mimo że jej nie używam i voila, działa. Więc może nie powiedzieć, że jest to wymagane, ale relacje bez odwrotności mogą zdecydowanie mieć dziwne skutki uboczne.

 4
Author: greg,
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
2015-02-07 04:28:33

Nie ma potrzeby odwrotnej relacji ogólnie. Ale jest kilka dziwactw/błędów w podstawowych danych, gdzie potrzebujesz odwrotnej relacji. Istnieją przypadki, w których relacje / obiekty giną , nawet jeśli nie ma błędu podczas zapisywania kontekstu, jeśli brakuje odwrotnej relacji. Sprawdź ten Przykład , który stworzyłem, aby zademonstrować brakujące obiekty i jak obejść problem podczas pracy z podstawowymi danymi

 1
Author: Dhilip,
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-10-15 17:02:55

Odwrotności są również używane dla Object Integrity (z innych powodów, zobacz inne odpowiedzi):

Zalecanym podejściem jest modelowanie relacji w obu kierunkach i odpowiednio określić relacje odwrotne. Podstawowe zastosowania danych tych informacji w celu zapewnienia spójności wykresu obiektowego, jeżeli zmiana dokonywana

Od: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreData/HowManagedObjectsarerelated.html#//apple_ref/doc/uid/TP40001075-CH17-SW1

Podany link daje Ci pomysły, dlaczego powinieneś mieć zestaw inverse. Bez niego możesz stracić dane / liczbę całkowitą. Ponadto szansa, że uzyskasz dostęp do obiektu, który jest nil, jest bardziej prawdopodobna.

 0
Author: J. Doe,
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-02-15 15:00:29