2009-04-18 4 views
132

मान लें कि मेरे पास दो इकाई वर्ग हैं: SocialApp और SocialAppTypeक्या प्रत्येक कोर डेटा रिलेशनशिप में उलटा होना चाहिए?

SocialApp में मेरे पास एक विशेषता है: appURL और एक रिश्ता: type

SocialAppType में मेरे पास तीन विशेषताएं हैं: baseURL, name और favicon

SocialApp संबंध type का गंतव्य SocialAppType में एक एकल रिकॉर्ड है।

एक उदाहरण के रूप में, एकाधिक फ़्लिकर खातों के लिए, कई SocialApp रिकॉर्ड्स होंगे, प्रत्येक रिकॉर्ड के साथ किसी व्यक्ति के खाते में एक लिंक होगा। "फ़्लिकर" प्रकार के लिए एक SocialAppType रिकॉर्ड होगा, कि सभी SocialApp रिकॉर्ड्स इंगित करेंगे।

जब मैं इस स्कीमा के साथ एक अनुप्रयोग बनाता हूं, मुझे एक चेतावनी मिलती है कि SocialAppType और SocialApp के बीच कोई व्यस्त संबंध नहीं है।

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

क्या मुझे एक व्यस्त की आवश्यकता है, और क्यों?

उत्तर

107

व्यवहार में, मैं एक व्युत्क्रम नहीं होने की वजह से किसी भी डेटा हानि नहीं पड़ा है - कम से कम है कि मैं के बारे में पता कर रहा हूँ। एक त्वरित गूगल पता चलता है कि आप उन्हें इस्तेमाल करना चाहिए:

एक व्युत्क्रम संबंध सिर्फ चीजें अधिक साफ नहीं है, यह वास्तव में कोर डाटा द्वारा इस्तेमाल किया डेटा बनाए रखने के लिए अखंडता है।

- Cocoa Dev Central

आप आमतौर पर दोनों दिशाओं में रिश्तों मॉडल चाहिए, और उलटा रिश्तों उचित रूप से निर्दिष्ट करें। कोर डाटा वस्तु ग्राफ की निरंतरता सुनिश्चित करने के लिए अगर एक परिवर्तन बनाई गई है (देखें "जोड़ तोड़ रिश्ते और ग्राफ़ वफ़ादारी वस्तु") इस जानकारी का उपयोग करता। कारण आप दोनों दिशाओं में एक संबंध मॉडल नहीं करना चाह सकते हैं में से कुछ का चर्चा, और समस्याओं में से कुछ है कि पैदा हो सकता है यदि आप नहीं करते हैं, यह देखने के लिए "यूनिडायरेक्शनल रिश्ते।"

- Core Data Programming Guide

+5

मैडनिक का जवाब (इस पृष्ठ के निचले हिस्से में देखें कि इस समय मैं इसे लिख रहा हूं) के बारे में अधिक व्यापक स्पष्टीकरण के लिए देखें कि जब वे कहते हैं कि व्यस्त रिश्ते डेटा अखंडता को बनाए रखने में मदद करते हैं। –

21

बेहतर सवाल यह है कि, "वहाँ एक कारण नहीं एक व्युत्क्रम है"? कोर डेटा वास्तव में एक ऑब्जेक्ट ग्राफ़ प्रबंधन ढांचा है, एक दृढ़ता ढांचा नहीं। दूसरे शब्दों में, इसका काम ऑब्जेक्ट ग्राफ़ में ऑब्जेक्ट्स के बीच संबंधों का प्रबंधन करना है। उलटा रिश्तों इस ज्यादा आसान बनाते हैं। इसी कारण से, कोर डेटा व्यस्त संबंधों की अपेक्षा करता है और उस उपयोग के मामले के लिए लिखा जाता है। उनके बिना, आपको ऑब्जेक्ट ग्राफ़ स्थिरता को स्वयं प्रबंधित करना होगा।विशेष रूप से, एक व्यस्त संबंध के बिना कई रिश्ते कोर डेटा द्वारा दूषित होने की संभावना है जब तक कि आप बहुत काम करने के लिए कड़ी मेहनत करते हैं। व्यस्त रिश्तों के लिए डिस्क आकार के मामले में लागत वास्तव में लाभ के मुकाबले कमजोर है।

44

मैं में प्राप्त किए गए निश्चित उत्तर को स्पष्ट करता हूं, डेव मार्क और जेफ लीमार द्वारा अधिक आईफोन 3 विकास

ऐप्पल आम तौर पर अनुशंसा करता है कि आप हमेशा व्यस्त बनाते हैं और निर्दिष्ट करते हैं, भले ही आप अपने ऐप में व्यस्त रिश्तों का उपयोग न करें। इस कारण से, यह आपको चेतावनी देता है कि जब आप एक उलटा प्रदान करने में असफल होते हैं।

रिश्ते आवश्यक नहीं हैं, क्योंकि कुछ परिदृश्य हैं जिनमें व्यस्त संबंध प्रदर्शन को नुकसान पहुंचा सकता है। उदाहरण के लिए, मान लीजिए कि व्यस्त संबंधों में वस्तुओं की एक बड़ी संख्या होती है। उलटा हटाने के लिए सेट पर पुनरावृत्ति की आवश्यकता होती है जो व्यस्त, कमजोर प्रदर्शन का प्रतिनिधित्व करती है।

लेकिन जब तक आपके पास कोई विशिष्ट कारण न हो, तो उलटा मॉडल करें। यह कोर डेटा डेटा अखंडता सुनिश्चित करने में मदद करता है। यदि आप प्रदर्शन समस्याओं में भाग लेते हैं, तो बाद में व्यस्त संबंधों को दूर करना अपेक्षाकृत आसान है।

112

ऐप्पल प्रलेखन का एक अच्छा उदाहरण है जो एक ऐसी स्थिति का सुझाव देता है जहां आपको प्रतिकूल रिश्ते न होने पर समस्या हो सकती है। आइए इसे इस मामले में मैप करें।

मान लें कि आप इसे मॉडलिंग की इस प्रकार है: enter image description here

नोट आप "प्रकार" नामक एक टू-वन संबंध, SocialApp से SocialAppType किया है। रिश्ते गैर-वैकल्पिक है और "deny" नियम हटाएं।

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

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

क्या हम उम्मीद करते हैं कि इस संदर्भ बचाने के बाद से हम नष्ट नियम जबकि संबंध गैर वैकल्पिक है इंकार के रूप में स्थापित किया है विफल है:

अब निम्नलिखित पर विचार करें।

लेकिन यहां बचत सफल होती है।

कारण यह है कि हमने व्यस्त रिश्ते सेट नहीं किया है। इसके कारण, ऐपटाइप हटा दिए जाने पर सोशल ऐप इंस्टेंस को बदला नहीं जाता है। इसलिए सहेजने से पहले सोशल ऐप के लिए कोई सत्यापन नहीं होता है (कोई बदलाव होने के बाद यह कोई सत्यापन आवश्यक नहीं है)। लेकिन वास्तव में एक बदलाव हुआ। लेकिन यह परिलक्षित नहीं होता है।

अगर हम द्वारा

SocialAppType *appType = [socialApp socialAppType]; 

appType appType याद नहीं के बराबर है।

अजीब, है ना? हम एक गैर-वैकल्पिक विशेषता के लिए शून्य पाते हैं?

तो यदि आप व्यस्त संबंध स्थापित करते हैं तो आपको कोई परेशानी नहीं है। अन्यथा आपको निम्नानुसार कोड लिखकर बल सत्यापन करना होगा।

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

यह एक अच्छा जवाब है; स्पष्ट विवरण में वर्तनी के लिए धन्यवाद - दस्तावेज़ों से, और मैंने जो कुछ भी पढ़ा है - सब कुछ के लिए उलटा होने के पक्ष में मुख्य तर्क, यहां तक ​​कि जहां प्रतिकूल संबंध मानव रूप से सार्थक नहीं है। यह वास्तव में स्वीकार्य उत्तर होना चाहिए।यह सब प्रश्न थ्रेड गायब है अब आप कारणों का अधिक विस्तृत अन्वेषण कर सकते हैं * आप * इनवर्स को चुनने के लिए चुन सकते हैं, गुलाब पेरोन के जवाब में स्पर्श किया गया है (और दस्तावेज में भी थोड़ा सा)। –

17

कम से कम एक परिदृश्य में जहाँ एक अच्छा मामला एक व्युत्क्रम के बिना एक कोर डेटा रिश्ते के लिए बनाया जा सकता है: जब वहाँ पहले से ही दो वस्तुओं के बीच एक और कोर डेटा संबंध है, जो वस्तु ग्राफ बनाए रखने संभाल लेंगे है।

उदाहरण के लिए, एक पुस्तक में कई पेज होते हैं, जबकि एक पृष्ठ एक पुस्तक में होता है। यह दो-तरफा कई से एक रिश्ते है। एक पृष्ठ को हटाने से रिश्ते को खत्म कर दिया जाता है, जबकि एक पुस्तक को हटाने से पेज को भी हटा दिया जाएगा।

हालांकि, आप प्रत्येक पुस्तक के लिए वर्तमान पृष्ठ को पढ़ने के लिए भी ट्रैक करना चाहेंगे। यहपर पर पर पर किया जा सकता है, लेकिन फिर आपको यह सुनिश्चित करने के लिए अन्य तर्क की आवश्यकता है कि पुस्तक में केवल एक पृष्ठ किसी भी समय वर्तमान पृष्ठ के रूप में चिह्नित किया गया हो। इसके बजाए, एक वर्तमान पृष्ठ रिश्ते को एक पृष्ठ से पुस्तक से रिश्ते सुनिश्चित करने से यह सुनिश्चित होगा कि हमेशा एक वर्तमान पृष्ठ चिह्नित होगा, और इसके अलावा यह पृष्ठ आसानी से book.currentPage के साथ पुस्तक के संदर्भ के साथ आसानी से पहुंचा जा सकता है।

Graphical presentation of core data relationship between books and pages

पारस्परिक सम्बन्ध इस मामले में क्या होगा? कुछ हद तक गैरकानूनी। "myBook" या इसी तरह को दूसरी दिशा में वापस जोड़ा जा सकता है, लेकिन इसमें पृष्ठ के लिए "पुस्तक" संबंध में पहले से मौजूद जानकारी शामिल है, और इसलिए अपने जोखिम पैदा करता है। शायद भविष्य में, आप इन संबंधों में से किसी एक का उपयोग कर रहे हैं, जिसके परिणामस्वरूप आपके मूल डेटा कॉन्फ़िगरेशन में परिवर्तन हुए हैं। यदि पेज.मेबुक का उपयोग कुछ स्थानों पर किया गया है जहां कोड में पेज.बुक का इस्तेमाल किया जाना चाहिए था, तो समस्याएं हो सकती हैं। सक्रिय रूप से इससे बचने का एक और तरीका यह भी होगा कि पेज को एक्सेस करने के लिए उपयोग किए जाने वाले एनएसएमएनेज्ड ऑब्जेक्ट उपclass में myBook का पर्दाफाश न करें। हालांकि, यह तर्क दिया जा सकता है कि पहले स्थान पर उलटा मॉडल करना आसान है।

उदाहरण में उल्लिखित उदाहरण में, वर्तमान पेज रिलेशनशिप के लिए डिलीट नियम "नो एक्शन" या "कैस्केड" पर सेट होना चाहिए, क्योंकि "Nullify" के लिए कोई पारस्परिक संबंध नहीं है। (कास्केड का तात्पर्य है कि आप पुस्तक के बाहर से प्रत्येक पेज को फिसल रहे हैं, लेकिन यह सच हो सकता है यदि आप विशेष रूप से ठंडे हैं और ईंधन की आवश्यकता है।)

जब यह प्रदर्शित किया जा सकता है कि ऑब्जेक्ट ग्राफ़ अखंडता जोखिम में नहीं है , जैसा कि इस उदाहरण में है, और कोड जटिलता और रखरखाव में सुधार हुआ है, यह तर्क दिया जा सकता है कि एक उलटा बिना संबंध सही निर्णय हो सकता है।

+0

धन्यवाद डंकन - यह मेरे पास उपयोग के मामले के बहुत करीब है। अनिवार्य रूप से, मुझे एक पुस्तक के ** अंतिम पृष्ठ ** प्राप्त करने में सक्षम होना चाहिए। मुझे इसे एक स्थिर मूल्य होने की आवश्यकता है ताकि मैं इसे एक अनुमानित भविष्यवाणी में उपयोग कर सकूं। मैंने एक "bookIAmLastPageOf" उलटा स्थापित किया था, लेकिन यह बहुत मूर्खतापूर्ण है और अन्य समस्याएं पैदा कर रहा है (मैं ठीक से समझ नहीं पा रहा हूं)। क्या आपको पता है कि एक मामले के लिए चेतावनी को अक्षम करने का कोई तरीका है या नहीं? – Benjohn

+0

क्या चेतावनियों को अक्षम करने का कोई तरीका है? अब मेरे पास 2: * है ... एक उलटा * होना चाहिए और * कोई क्रिया हटाएं नियम ... परिणामस्वरूप हटाए गए ऑब्जेक्ट्स के रिश्ते * हो सकते हैं। और 'currentPage' को' वैकल्पिक 'के रूप में चिह्नित किया जा सकता है? – SwiftArchitect

+0

रिश्ते के बजाय वर्तमान पृष्ठ को एनएसएमएनेज्ड ओब्जेक्टिड के रूप में संग्रहीत करना एक वैध दृष्टिकोण होगा? – user965972

4

जबकि दस्तावेज़ों को एक व्यस्त की आवश्यकता नहीं लगती है, मैंने अभी एक परिदृश्य का समाधान किया है जिसके परिणामस्वरूप एक उलटा होने के कारण "डेटा हानि" का परिणाम हुआ। मेरे पास एक रिपोर्ट ऑब्जेक्ट है जिसमें रिपोर्ट करने योग्य ऑब्जेक्ट्स पर बहुत से संबंध हैं। व्यस्त संबंधों के बिना, पुन: लॉन्च होने पर कई रिश्ते में कोई भी परिवर्तन खो गया था। कोर डेटा डीबग का निरीक्षण करने के बाद यह स्पष्ट था कि हालांकि मैं रिपोर्ट ऑब्जेक्ट को सहेज रहा था, ऑब्जेक्ट ग्राफ़ (रिलेशनशिप) के अपडेट कभी नहीं किए जा रहे थे। मैंने एक उलटा जोड़ा, भले ही मैं इसका उपयोग नहीं करता, और voila, यह काम करता है। तो शायद यह नहीं कह सकता कि यह आवश्यक है लेकिन इनवर्क्स के बिना संबंध निश्चित रूप से अजीब दुष्प्रभाव हो सकते हैं।