모든 핵심 데이터 관계에 역수가 있어야합니까?


150

의 내가 두 엔티티 클래스가 있다고 가정 해 봅시다 : SocialAppSocialAppType

에서 SocialApp: 나는 하나 개의 속성이 appURL하나 개의 관계 : type.

에서 SocialAppType나는 세 가지 속성이 있습니다 baseURL, name하고 favicon.

SocialApp관계 의 대상 type은의 단일 레코드입니다 SocialAppType.

예를 들어, 여러 Flickr 계정의 경우 여러 SocialApp레코드가 있으며 각 레코드에는 개인의 계정에 대한 링크가 있습니다. SocialAppType"Flickr"유형에는 모든 SocialApp레코드가 가리키는 하나의 레코드 가 있습니다 .

나는이 스키마를 사용하여 응용 프로그램을 빌드 할 때 사이에 반비례 관계가 없다는 것을, 내가 경고를 SocialAppType하고 SocialApp.

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

역수가 필요한 이유는 무엇입니까?

답변:


117

실제로, 나는 적어도 내가 알고있는 역수가 없기 때문에 데이터 손실이 없었습니다. 빠른 Google은 다음을 사용해야한다고 제안합니다.

역의 관계는 일을 더 깔끔하게 만드는 것이 아니라 실제로 데이터 무결성을 유지하기 위해 Core Data에서 사용됩니다.

- 코코아 데브 센트럴

일반적으로 관계를 양방향으로 모델링하고 역관계를 적절하게 지정해야합니다. Core Data는이 정보를 사용하여 변경시 객체 그래프의 일관성을 유지합니다 (“관계 및 객체 그래프 무결성 조작”참조). 양방향으로 관계를 모델링하지 않을 수있는 몇 가지 이유와 그렇지 않은 경우 발생할 수있는 일부 문제에 대한 내용은“단방향 관계”를 참조하십시오.

- 핵심 데이터 프로그래밍 안내서


5
역관계가 데이터 무결성을 유지하는 데 도움이된다고 할 때 문서가 무엇을 의미하는지에 대한 자세한 설명은 MadNik의 답변 (이 글을 쓰는 순간 페이지 하단에 있음)을 참조하십시오.
Mark Amery

135

Apple 설명서에는 역의 관계가 없어서 문제가 발생할 수있는 상황을 나타내는 훌륭한 예가 있습니다. 이 경우에 매핑합시다.

다음과 같이 모델링했다고 가정하십시오. 여기에 이미지 설명을 입력하십시오

당신은이 주 에 - 하나 "라는 관계 유형 에서," SocialAppSocialAppType. 관계는 선택 사항아니며 "거부"삭제 규칙이 있습니다.

이제 다음을 고려하십시오.

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

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

관계가 선택 사항이 아닌 반면 삭제 규칙을 거부로 설정했기 때문에이 컨텍스트 저장에 실패합니다.

그러나 여기서 절약은 성공합니다.

그 이유는 우리가 반비례 관계를 설정하지 않았기 때문입니다 . 따라서 appType이 삭제 될 때 socialApp 인스턴스가 변경된 것으로 표시되지 않습니다. 따라서 저장하기 전에 socialApp에 대한 유효성 검증이 수행되지 않습니다 (변경이 발생하지 않았으므로 유효성 검증이 필요하지 않은 것으로 가정 함). 그러나 실제로 변화가 일어났습니다. 그러나 반영되지 않습니다.

우리가 appType을 리콜하면

SocialAppType *appType = [socialApp socialAppType];

appType은 nil입니다.

이상하지 않습니까? 선택 사항이 아닌 속성에 대해서는 0을 얻습니까?

따라서 당신은 역관계를 설정해도 아무런 문제가 없습니다. 그렇지 않으면 다음과 같이 코드를 작성하여 강제 유효성 검사를 수행해야합니다.

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];

9
이것은 훌륭한 답변입니다. 문서의 내용과 내가 읽은 모든 내용을 명확하게 자세하게 설명해 주셔서 감사합니다. 반역 관계가 인간적으로 의미가없는 경우에도 모든 것에 반비례를 갖는 주요 논거입니다. 이것은 실제로 받아 들여질만한 대답이어야합니다. 이 질문 스레드가 이제 누락되었습니다 . Rose Perrone의 답변 (및 문서에서도 약간)을 거꾸로 하지 않기로 선택할 수있는 이유에 대한 더 자세한 탐색입니다 .
Mark Amery

46

필자는 Dave Mark와 Jeff LeMarche의 More iPhone 3 Development 에서 찾은 확실한 답을 역설 할 것입니다.

Apple은 일반적으로 앱에서 역 관계를 사용하지 않더라도 항상 역을 만들고 지정하는 것이 좋습니다. 이러한 이유로 역을 제공하지 않으면 경고합니다.

역 관계가 성능을 손상시킬 수있는 몇 가지 시나리오가 있기 때문에 관계에 역이 필요 하지 않습니다 . 예를 들어, 역의 관계에 매우 많은 수의 객체가 포함되어 있다고 가정합니다. 역수를 제거하려면 역 약화 성능을 나타내는 집합을 반복해야합니다.

그러나 특별한 이유가 없다면 inverse를 모델링하십시오 . Core Data는 데이터 무결성을 보장합니다. 성능 문제가 발생하면 나중에 반비례 관계를 쉽게 제거 할 수 있습니다.


24

더 좋은 질문은 " 반대 하지 않는 이유 가 있습니까?"입니다. 핵심 데이터는 실제로 지속성 프레임 워크가 아닌 객체 그래프 관리 프레임 워크입니다. 즉, 그 역할은 객체 그래프에서 객체 간의 관계를 관리하는 것입니다. 역관계는 훨씬 쉬워집니다. 이러한 이유로 Core Data는 역의 관계를 기대하며 해당 사용 사례를 위해 작성되었습니다. 그것들이 없으면 객체 그래프 일관성을 직접 관리해야합니다. 당신이 작동하지 않는 특히, 역 관계없이 일대 다 관계는 매우 가능성이 코어 데이터가 손상 될 수 있습니다 매우 작업하게 유지하기 어렵다. 역 관계에 대한 디스크 크기 측면에서 비용은 실제로 얻는 이점과 비교하여 중요하지 않습니다.


20

역전없이 핵심 데이터 관계에 대해 좋은 사례를 만들 수있는 시나리오가 적어도 하나 있습니다. 두 객체 사이에 다른 핵심 데이터 관계가 이미있는 경우 객체 그래프 유지 관리를 처리합니다.

예를 들어, 책에 여러 페이지가 포함되어 있고 한 페이지에 페이지가 있습니다. 이것은 양방향 다 대일 관계입니다. 페이지를 삭제하면 관계가 무효가되고 책을 삭제하면 페이지도 삭제됩니다.

그러나 각 책에 대해 현재 읽고있는 페이지를 추적 할 수도 있습니다. 이것은 "currentPage"와 함께 할 수있는 재산페이지 ,하지만 당신은 책의 한 페이지가 언제든지 현재의 페이지로 표시되어 있는지 확인하기 위해 다른 논리가 필요합니다. 대신, Book에서 단일 페이지로 currentPage 관계 를 설정하면 항상 하나의 현재 페이지 만 표시되며, book.currentPage를 사용하여 책을 참조하여이 페이지에 쉽게 액세스 할 수 있습니다.

책과 페이지 간의 핵심 데이터 관계를 그래픽으로 표현

이 경우 상호 관계는 무엇입니까? 무의미한 것. "myBook"또는 이와 유사한 항목을 다른 방향으로 다시 추가 할 수 있지만 페이지에 대한 "book"관계에 이미 포함 된 정보 만 포함되므로 자체 위험이 발생합니다. 아마도 미래에는 이러한 관계 중 하나를 사용하는 방식이 변경되어 핵심 데이터 구성이 변경 될 수 있습니다. 코드에서 page.book을 사용해야하는 곳에서 page.myBook을 사용한 경우 문제가있을 수 있습니다. 이를 사전에 피하는 또 다른 방법은 페이지에 액세스하는 데 사용되는 NSManagedObject 서브 클래스에 myBook을 노출시키지 않는 것입니다. 그러나 처음에는 역을 모델링하지 않는 것이 더 간단하다고 주장 할 수 있습니다.

설명 된 예에서 currentPage 관계에 대한 삭제 규칙은 "Nullify"에 대한 상호 관계가 없으므로 "No Action"또는 "Cascade"로 설정해야합니다. (캐스케이드는 책을 읽을 때 모든 페이지를 책에서 추출한다는 것을 의미하지만, 특히 차가워서 연료가 필요한 경우에 해당 될 수 있습니다.)

이 예에서와 같이 객체 그래프 무결성이 위험하지 않다는 것이 입증 될 수 있고 코드 복잡성 및 유지 관리 성이 개선되면, 역의 관계가없는 관계가 올바른 결정일 수 있다고 주장 할 수 있습니다.


고마워 Duncan – 이것은 내가 가진 유스 케이스에 매우 가깝습니다. 본질적으로, 나는 책 의 마지막 페이지 를 얻을 수 있어야합니다 . 페치 술어에서 사용할 수 있도록 지속 값이어야합니다. "bookIAmLastPageOf"를 반대로 설정했지만, 그것은 무의미하고 다른 문제를 일으 킵니다 (올바로 이해하지 못합니다). 단일 사례에 대해 경고를 비활성화 할 수있는 방법이 있는지 알고 있습니까?
Benjohn

경고를 비활성화하는 방법이 있습니까? 나는 이제 2 : ... 반전 하고 액션 삭제 규칙이 없어야 ... 삭제 된 객체와의 관계가 발생할 수 있습니다 . 그리고 수 currentPage로 표시 Optional?
SwiftArchitect

관계 대신 현재 페이지를 NSManagedObjectID로 저장하는 것이 유효한 방법입니까?
user965972

4

문서에는 역수가 필요하지 않은 것처럼 보이지만 실제로는 역이 없어서 "데이터 손실"이 발생하는 시나리오를 해결했습니다. 보고 가능한 개체와 많은 관계가있는 보고서 개체가 있습니다. 반비례 관계가 없으면 다 대다 관계에 대한 변경 사항이 다시 시작될 때 손실되었습니다. 핵심 데이터 디버그를 검사 한 후 보고서 개체를 저장하더라도 개체 그래프 (관계)에 대한 업데이트가 수행되지 않았 음을 알 수있었습니다. 나는 그것을 사용하지 않더라도 역을 추가했으며, voila는 작동합니다. 따라서 그것이 필요하다고 말할 수는 없지만 역수가없는 관계는 분명히 이상한 부작용을 가질 수 있습니다.


0

역수도 사용됩니다 Object Integrity(다른 이유로 다른 답변 참조).

권장되는 방법은 양방향 관계를 모델링하고 역관계를 적절하게 지정하는 것입니다. Core Data는이 정보를 사용하여 변경시 객체 그래프의 일관성을 보장합니다.

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

제공된 링크는 왜 inverse세트 가 필요한지에 대한 아이디어를 제공합니다 . 그것 없이는 데이터 / 무결성을 잃을 수 있습니다. 또한 nil더 가능성이 높은 개체에 액세스 할 가능성이 있습니다.


0

반비례 관계는 일반적으로 필요하지 않습니다. 그러나 코어 데이터에는 역의 관계가 필요한 쿼크 / 버그가 거의 없습니다. 반대 관계가없는 경우 컨텍스트를 저장하는 동안 오류가 없더라도 관계 / 객체가 누락되는 경우가 있습니다. Core 데이터로 작업하는 동안 누락 된 객체와 해결 방법을 보여주기 위해 만든 이 예제를 확인하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.