Gegeben das folgende erfundene Beispiel:
Ich möchte meine Daten für alle Objekte abfragen, die entweder Katzen oder Hunde sind. Ich möchte das Ergebnis sortiert nach Namen, unabhängig von der Art, so dass alle Katzen holen und dann alle Hunde holen nicht tun. Ich möchte dies in einer einzigen Abfrage tun.
Eine Möglichkeit wäre, ein PetType-Feld zu Pet hinzuzufügen, jedem Datensatz einen petType-Wert zu geben, der die zugehörige Unterentität identifiziert, und dann wie folgt abzufragen:
%Vor%Aber der bloße Gedanke, es so zu machen, lässt mich schaudern. Gibt es einen besseren Weg?
Update : Vielen Dank an alle, die geantwortet haben - es gibt einige wirklich gute, durchdachte Lösungen hier und ich schätze sie alle.
Um dies zu verdeutlichen, ist das reale Datenmodell etwas komplexer (nicht immer), aber es ist ziemlich gut organisiert. Ich habe in meiner Zeit mehr als meinen gerechten Anteil an Datenschemata entworfen, und ich bin froh, dass die Entitäten und ihre Beziehungen gut durchdacht sind. Dieses Problem ist entstanden, weil (um das bereits wackelige erfundene Beispiel zu erweitern) der ursprünglich gewünschte Client:
So weit, so gut. Aber sie wollen auch eine Ansicht, die eine kombinierte Liste aller Katzen und Hunde zeigt, "weil kleine Mädchen wie Katzen und Hunde mögen". (Am Anfang waren es Katzen und Goldfische, aus dem gleichen Grund.) Es gibt nicht wirklich eine Möglichkeit, diese Teilmenge der konkreten Entitäten auf natürliche Weise zu gruppieren; es ist wirklich ziemlich willkürlich.
Bis jetzt scheint Dave Dribins Ansatz der "abstrakten Zwischeneinheit" die sauberste Lösung zu sein, obwohl ich denke, dass es sich irgendwie künstlich anfühlen würde; wirklich die einzige Art und Weise, wie du die dazwischenliegende Entität wahrheitsgemäß bezeichnen könntest, wäre "ThingLittleGirlsLike"! :)
Wie Sie herausgefunden haben, können Sie entity.name
nicht in Ihrem Abrufprädikat für SQLite-Speicher verwenden (Sie können > es für andere Geschäftstypen verwenden). Sie können ein petType
hinzufügen, wie Sie vorschlagen, was gut genug funktioniert, aber mich auch schaudern lässt. Alternativ können Sie alle Pets
abrufen und dann die abgerufenen Ergebnisse basierend auf entity.name
filtern. Aber das ist ein wenig ineffizient, da Sie mehr Entitäten laden, als Sie benötigen, und Ihre In-Memory-Filterung, die SQLite in Ihrem Namen tun könnte.
Ich denke, die wirkliche Frage ist: Was versuchst du zu tun? Wenn Sie wirklich Cats
und Dogs
ohne Goldfish
holen müssen, sollte Ihr Modell das widerspiegeln. Sie könnten eine FourLeggedPet
abstrakte Entität als übergeordnetes Element von Cat
und Dog
einfügen. Verwenden Sie dann in Ihrer Abrufanforderung FourLeggedPet
als Entität mit setIncludesSubentities:YES
.
Ihre verwalteten Objekte haben bereits eine Haustierart: Sie haben ihre entity.name
. Wenn du nach allen Pet
-Entitäten suchst, die den Entitätsnamen @"Cat"
oder @"Dog"
haben, sollte das, denke ich.
Beispiel (schnell und schmutzig in Xcode eingegeben, so schlecht gestaltet):
%Vor%Dies protokolliert Folgendes:
2011-06-30 14: 46: 57.435 CDSubentityTest [5626: 407] Entitäten: ( "(Entität: Katze; ID: 0x10025f740 ; Daten: {\ n Name = Fäustlinge; \ n}) ", "(Einheit: Hund; ID: 0x1002914e0 ; Daten: {\ n Name = Rover; \ n}) ")
Beachten Sie das erwartete Verschwinden des Goldfisches.
Ich glaube, der von Ihnen vorgeschlagene Ansatz würde gut funktionieren. Mit petType
können Sie auch Subtypen von Pet
s definieren (d. H. "Säugetiere", "Vögel", "Reptilien", "Fische" usw.). Natürlich könntest du stattdessen abstrakte Entitäten für jeden von diesen haben, aber es ist nicht klar, wie du davon auch profitieren würdest. Es hängt letztlich davon ab, wie Ihre Anwendung das Modell verwendet. Müssen Sie jemals alle Pet
s holen? Planen Sie die Möglichkeit, nur Cat
s und Fish
in einem einzigen Abruf zu erhalten? Möchten Sie Daten abrufen, die Sie nicht sofort verwenden?
Sobald Sie die erforderlichen Klassifizierungen basierend darauf definiert haben, wie Sie die Daten anzeigen / verwenden möchten, passen Sie das Modell an diese Klassifikationen an. Ein gutaussehendes, generisches Modell zu haben, kann oft ein Schmerz im Hintern sein, um es zu benutzen ...
Prädikate erkennen Entitäten nicht, sodass Sie kein Prädikat konstruieren können, um sie zu finden. (Update: Dies gilt nur für SQL-Stores.)
Wenn Sie Ihr Herz auf das Holen nach Haustierart eingestellt haben, haben Sie keine andere Wahl als ein Attribut anzugeben, das den Wert des Haustiertyps liefert und Prädikate und Fetches funktionieren lässt. Sie können jedoch eine wesentlich sauberere und sicherere Version als die von Ihnen vorgeschlagene Version erstellen.
petType
-Attribut (es kann nicht in der Entität geerbt werden, kann aber in benutzerdefinierten NSManagedObject-Unterklassen vererbt werden.) Überschreiben Sie die Setter-Methode, um nichts effektiv zu machen, wodurch das Attribut nur gelesen wird. (Dies kann von einer gemeinsamen Oberklasse geerbt werden.)
%Vor% Um nun alle Hunde und Katzen zu finden, müssen Sie nur noch die fetch-Entity auf Pet
setzen und dann ein Array von Pet-Type-Namen für den Operator IN
angeben.
Während das funktioniert, denke ich, dass Dave Dribin machte den besten Punkt. Diese Art von Hack wird normalerweise benötigt, wenn Sie Ihr Datenmodell nicht richtig verfeinert haben. Wenn Sie verschiedene Haustiere nach Haustier-Typ gruppieren müssen, dann gehört diese Gruppierung wahrscheinlich zu einem anderen realen Objekt, Zustand oder Ereignis, z. Besitzer, der wiederum mit Beziehungen zu bestimmten Pet-Instanzen modelliert werden sollte. Wenn Sie das tun, geschieht Ihre Gruppierung automatisch und Sie müssen nicht mit all dem herumspielen.
Tags und Links objective-c cocoa core-data