Her Temel Veri İlişkisinin Tersi Olmalı mı?


150

Diyelim ki iki Varlık sınıfım var: SocialAppveSocialAppType

In SocialApp: Bir Özellik var appURLve bir İlişki: type.

Gelen SocialAppTypeüç Öznitelikler'i vardır: baseURL, nameve favicon.

SocialAppİlişkinin hedefi, içindeki typetek bir kayıttır SocialAppType.

Örnek olarak, birden fazla Flickr hesabı için, SocialAppher kayıt bir kişinin hesabına bağlantı içeren bir dizi kayıt olacaktır . SocialAppTypeTüm SocialAppkayıtların göstereceği "Flickr" türü için tek bir kayıt olacaktır.

Bu şema ile bir uygulama oluşturduğumda, SocialAppTypeve arasında ters bir ilişki olmadığına dair bir uyarı alıyorum SocialApp.

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

Tersine ihtiyacım var mı ve neden?

Yanıtlar:


117

Uygulamada, tersine sahip olmadığım için veri kaybım olmadı - en azından farkındayım. Hızlı bir Google bunları kullanmanız gerektiğini önerir:

Ters ilişki sadece işleri daha düzenli hale getirmekle kalmaz, aynı zamanda Core Data tarafından veri bütünlüğünü korumak için kullanılır.

- Kakao Dev Central

Genellikle ilişkileri her iki yönde de modellemeli ve ters ilişkileri uygun şekilde belirtmelisiniz. Temel Veriler, bir değişiklik yapıldığında nesne grafiğinin tutarlılığını sağlamak için bu bilgileri kullanır (bkz. “İlişkileri ve Nesne Grafiği Bütünlüğünü Değiştirme”). Her iki yönde de bir ilişkiyi modellemek istememenizin bazı nedenleri ve bunu yapmazsanız ortaya çıkabilecek sorunların bazıları hakkında bir tartışma için bkz. “Tek Yönlü İlişkiler”.

- Temel Veri Programlama Kılavuzu


5
Dokümanların ters ilişkilerin veri bütünlüğünü korumaya yardımcı olduğunu söylediklerinde daha kapsamlı bir açıklama için MadNik'in cevabına (bunu yazdığım sayfanın altında) bakın.
Mark Amery

135

Apple belgelerinde, ters bir ilişki olmadan sorun yaşayabileceğiniz bir durum öneren harika bir örnek vardır. Bunu bu davaya eşleştirelim.

Aşağıdaki şekilde modellediğinizi varsayalım: resim açıklamasını buraya girin

İle arasında " type " adlı bire bir ilişkiniz olduğunu unutmayın . İlişkiSocialAppSocialAppType isteğe bağlı değildir ve bir "reddet" silme kuralına sahiptir .

Şimdi aşağıdakileri göz önünde bulundurun:

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

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

Beklediğimiz şey, ilişki isteğe bağlı olmadığında delete kuralını Reddet olarak ayarladığımız için bu bağlamı kaydetmemek.

Ama burada tasarruf başarılı.

Nedeni ters bir ilişki kurmamamız . Bu nedenle, appType silindiğinde socialApp örneği değiştirildi olarak işaretlenmez. Dolayısıyla, kaydetmeden önce socialApp için hiçbir doğrulama gerçekleşmez (herhangi bir değişiklik olmadığı için hiçbir doğrulama gerekmediğini varsayar). Ama aslında bir değişiklik oldu. Ama yansıtılmıyor.

Uygulamayı hatırlarsak

SocialAppType *appType = [socialApp socialAppType];

appType sıfırdır.

Tuhaf, değil mi? İsteğe bağlı olmayan bir özellik için nil alıyoruz?

Ters ilişkiyi kurmuş olursanız sorun yaşamazsınız. Aksi takdirde, kodu aşağıdaki gibi yazarak kuvvet doğrulaması yapmanız gerekir.

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
Bu harika bir cevap; belgelerden ve okuduğum her şeyden - ters ilişkinin insani anlamlı olmadığı yerlerde bile, her şey için tersine dönme lehine olan ana argümanı açık bir şekilde hecelediğiniz için teşekkürler. Bu gerçekten kabul edilen cevap olmalı. Bütün bu soru parçacığı şimdi eksik seçtiğiniz açabilecek nedenleri daha ayrıntılı keşif olduğunu değil Gül PERRONE cevabı (ve biraz da, belgelerinde) 'de değindi inversler olması.
Mark Amery

46

Dave Mark ve Jeff LeMarche'dan Daha Fazla iPhone 3 Geliştirme'de bulduğum kesin cevabı tekrar yazacağım.

Apple, uygulamanızda ters ilişkiyi kullanmasanız bile genellikle tersi oluşturmanızı ve belirtmenizi önerir. Bu nedenle, tersini sağlamadığınız zaman sizi uyarır.

İlişkilerin tersi olması gerekmez , çünkü ters ilişkinin performansa zarar verebileceği birkaç senaryo vardır. Örneğin, ters ilişkinin çok fazla sayıda nesne içerdiğini varsayalım. Tersinin çıkarılması, ters, zayıflama performansını temsil eden kümenin tekrarını gerektirir.

Ancak , yapmamak için özel bir nedeniniz yoksa, tersini modelleyin . Temel Verilerin veri bütünlüğünü sağlamasına yardımcı olur. Performans sorunlarıyla karşılaşırsanız, ters ilişkiyi daha sonra kaldırmak nispeten kolaydır.


24

Daha iyi olan soru, " tersinin olmamasının bir nedeni var mı?" Temel Veriler gerçekten bir kalıcılık çerçevesi değil, bir nesne grafiği yönetim çerçevesidir. Başka bir deyişle, görevi nesne grafiğindeki nesneler arasındaki ilişkileri yönetmektir. Ters ilişkiler bunu çok daha kolay hale getirir . Bu nedenle Temel Veriler ters ilişkiler bekler ve bu kullanım durumu için yazılır. Onlar olmadan, nesne grafiği tutarlılığını kendiniz yönetmeniz gerekecektir. Özellikle, ters bir ilişki olmadan birçok ilişkinin, işleri çalışmaya devam etmek için çok fazla çalışmıyorsanız Çekirdek Veriler tarafından bozulma olasılığı yüksektir . Ters ilişkiler için disk boyutu açısından maliyet, size kazandığı yararla karşılaştırıldığında gerçekten önemsizdir.


20

Ters veri olmadan çekirdek veri ilişkisi için iyi bir vakanın yapılabileceği en az bir senaryo vardır: zaten iki nesne arasında, nesne grafiğinin bakımını yapacak başka bir temel veri ilişkisi olduğunda.

Örneğin, bir kitap çok sayıda sayfa içerirken, bir sayfa bir kitaptadır. Bu iki yönlü bire bir ilişkidir. Bir sayfayı silmek yalnızca ilişkiyi geçersiz kılar, bir kitabı silmek de sayfayı siler.

Ancak, her kitap için okunmakta olan sayfayı da izlemek isteyebilirsiniz. Buna "CurrentPage" ile yapılabilir mülkiyet üzerinde Page , ama o zaman kitapta yalnızca bir sayfa her zaman geçerli sayfa olarak işaretlenmiş sağlamak için diğer mantığı gerekir. Bunun yerine, Kitaptan tek bir sayfaya bir currentPage ilişkisi oluşturmak , her zaman yalnızca bir geçerli sayfanın işaretlenmesini sağlar ve ayrıca bu sayfaya yalnızca book.currentPage ile kitaba başvuru ile kolayca erişilebilir.

Kitaplar ve sayfalar arasındaki temel veri ilişkisinin grafik sunumu

Bu durumda karşılıklı ilişki ne olurdu? Büyük ölçüde saçma bir şey. "myBook" veya benzeri başka yöne eklenebilir, ancak yalnızca sayfa için "kitap" ilişkisinde bulunan bilgileri içerir ve bu nedenle kendi risklerini oluşturur. Belki gelecekte, bu ilişkilerden birini kullanma şekliniz değişerek temel veri yapılandırmanızda değişikliklere neden olur. Page.myBook kodda page.book'un kullanılması gereken bazı yerlerde kullanılmışsa, sorunlar olabilir. Proaktif olarak bundan kaçınmanın başka bir yolu da myBook'u sayfaya erişmek için kullanılan NSManagedObject alt sınıfında göstermemek olacaktır. Bununla birlikte, tersi ilk etapta modellememenin daha basit olduğu söylenebilir.

Belirtilen örnekte, currentulma ilişkisi için silme kuralı "Eylem Yok" veya "Basamakla" olarak ayarlanmalıdır, çünkü "Geçersiz Kılma" ile karşılıklı ilişki yoktur. (Cascade, her sayfayı okurken kitaptan kopardığınız anlamına gelir, ancak özellikle üşüyorsanız ve yakıta ihtiyacınız varsa bu doğru olabilir.)

Nesne grafiği bütünlüğünün bu örnekte olduğu gibi risk altında olmadığı ve kod karmaşıklığı ve sürdürülebilirliğinin geliştirildiği gösterilebildiğinde, tersi olmayan bir ilişkinin doğru karar olabileceği öne sürülebilir.


Teşekkürler Duncan - bu benim bir kullanım durumuna son derece yakın. Esasen, bir kitabın son sayfasını alabilmem gerekiyor . Ben bir getirme yükleminde kullanabilmek için bu kalıcı bir değer olması gerekir. Bir ters "bookIAmLastPageOf" kurmuştu, ama oldukça saçma ve diğer sorunlara (düzgün anlamıyorum) neden oluyor. Tek bir vaka için uyarıyı devre dışı bırakmanın bir yolu olup olmadığını biliyor musunuz?
Benjohn

Uyarıları devre dışı bırakmanın bir yolu var mı? Şimdi 2: ... ters olmalı ve Eylem Silme Kuralı Olmaması gerekir ... silinmiş nesnelerle ilişkilere neden olabilir . Ve currentPageolarak işaretlenebilir Optional?
SwiftArchitect

CurrentPage'i ilişki yerine NSManagedObjectID olarak depolamak geçerli bir yaklaşım mıdır?
user965972

4

Dokümanlar tersi gibi görünmese de, aslında "veri kaybı" ile sonuçlanan bir senaryoyu tersine çevirerek çözdüm. Raporlanabilir nesneler üzerinde çok fazla ilişkisi olan bir rapor nesnesi var. Ters ilişki olmadan, yeniden başlatma sırasında çok sayıda ilişkide herhangi bir değişiklik kaybedildi. Temel Veri hata ayıklamasını inceledikten sonra, rapor nesnesini kaydediyor olsam bile, nesne grafiğinde (ilişkiler) güncellemeler yapılmadı. Kullanmasam da tersini ekledim ve işe yarıyor. Bu yüzden gerekli olduğunu söyleyemeyebilir, ancak tersi olmayan ilişkilerin kesinlikle garip yan etkileri olabilir.


0

Tersler de kullanılır Object Integrity(diğer nedenlerle diğer cevaplara bakın):

Önerilen yaklaşım ilişkileri her iki yönde de modellemek ve ters ilişkileri uygun şekilde belirtmektir. Temel Veriler, bir değişiklik yapılırsa nesne grafiğinin tutarlılığını sağlamak için bu bilgileri kullanır

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

Sağlanan bağlantı, neden bir inversesetiniz olması gerektiği konusunda size fikir verir . Bu olmadan, veri / bütünlüğü kaybedebilirsiniz. Ayrıca, bir nesneye erişme şansınız nildaha olasıdır.


0

Genel olarak ters ilişkiye gerek yoktur. Ancak, çekirdek verilerde ters bir ilişkiye ihtiyacınız olan birkaç tuhaflık / hata var. Ters ilişki eksikse, bağlam kaydedilirken hata olmamasına rağmen, ilişkilerin / nesnelerin kaybolduğu durumlar vardır. Temel verilerle çalışırken eksik nesneleri ve nasıl geçici bir çözüm bulunacağını göstermek için oluşturduğum bu örneği kontrol edin

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.