Relationships in CoreData und SQL

  • Relationships in CoreData und SQL

    Hallo,

    in SQL kann ich so ziemlich alles machen mit einer Zeile Code, aber in CoreData fehlt mir noch der (schnelle) Zugang, z. B.:
    Ich habe ne Entity (Tabelle) Länder und eine Städte mit einer 1:N-Beziehung, d. h. jedes Land hat 0 - unendlich Städte, aber jeder Stadt ist genau ein Land zugeordnet.
    Diese Zuordnung ist in CoreData noch einfach hinzukriegen mit zwei Relationships, eine to-many in Länder auf Städte, eine reverse (not to-many) von Städten zurück auf Länder. Funktioniert alles wunderbar und im IB hat man in Sekunden eine kleine App zusammengeklickt.
    Städte und Länder sind per NSArrayController an NSTableViews "binded".

    Jetzt möchte ich, dass nur die Städte angezeigt werden der Länder, die selektiert sind. In SQL keine Problem"select städte.* from städte inner join länder on städte.derSchlüssel = länder.derSchlüssel where länder in ('das', 'das auch', 'und das');"
    Wie ich das in CoreData (per bindings oder per code) hinkriege, ist mir noch unklar. Ich kann zwar Filter per NSPredicates kreieren, aber dies sind ja mehr SQL-ähnliche Bedingungen für eine Entity, ich möchte ja die Relationen nutzen.

    Gibt es da einen Ansatz??
    ;) Bitte nicht "Das Buch" oder "Das Buch Teil 2", die liegen erst zu Weihnachten unterm Tannenbaum


    Viele Grüße fiveyears
  • Auch ich muss das mal probieren, was Amin vorschlägt.

    Ich hatte ein ähnliches Problem: ein Tabelle mit Ländern und eine mit Firmen. Eine 1:n Relationship soll für jedes Land die Beziehung zu den Firmen herstellen und umgekehrt die Firmen an das Land binden, in der sie liegt. Offensichtlich habe ich das nicht so richtig verstanden. Ich wollte sogar eine Root-Tabelle einbauen, die 1-n Relations zu den beiden anderen Tabellen hat. Ich war wohl einfach zu doof dazu. Anscheinend muss man diese Relationship nämlich per Code anlegen, da ich nämlich die Daten mit einem command line tool und einem Python-Skript aus CSV-Dateien importiere. Oder geht das doch automatisch? Ich weiß es nicht. Ich muss die Doku und die Samples wohl mal in Ruhe studieren und mir dann doch "die Bücher" dazu besorgen.

    Nun, ich habe es dann einfach gelassen, was in meiner app auch möglich war. Die Länder brauche ich nur für den Section-Header in TableViews und die Firmen haben ein Feld mit einer uid des Landes, damit kann ich selektieren und die TableCells füllen. So viele Datensätze hat die Datenbank auch nicht. Ein paar Zeilen Code haben mir mein Problem gelöst, wenn auch nicht auf die effizienteste und eleganteste Weise. Aber das kann ich mir für einen Update aufheben ;) Jetzt ist die App erst mal im Review und wird hoffentlich bald im Store sein.
  • CoreData ist keine Datenbank, sondern ein Framework zur Verwaltung von Objektgraphen.
    CoreData ist auch nicht dafür da, die Modellschicht ganz ohne Code hinzubekommen, sondern erleichtert deren Implementation (lästige Dinge wie Undo, Serialisierung, Validierung, Konsistenz der relationships etc.) - mit Tabellen hat das rein gar nichts zu tun. Apple schrieb selbst vor einiger Zeit, dass es keine Einsteigertechnologie ist und man mit den grundlegenden Cocoa-Konzepten vertraut sein muss, um es effizient zu benutzen (Speicherverwaltung, KVC/KVO, MVC).

    Zu Deiner Frage: um Daten aus einer externen Quelle in CoreData zu importieren, brauchst Du auf jeden Fall Code. In der Apple-Doku gibt es ein sehr schönes Videotutorial (noch aus seligen Tiger-Zeiten):

    developer.apple.com/cocoa/coredatatutorial/index.html

    Ansonsten Brief an den Weihnachtsmann mit der Frage nach "dem Buch" (oder den vielen anderen, u.a. auch hier geposteteten Lektüre-Empfehlungen -> SuFu).
  • Es ist mir schon klar, dass ich für den Datenimport selbst Code schreiben muss ;)
    Ich habe das auch bewusst mit einer Kombination von Command-Line Tool und Python-Skript gebastelt, weil das Parsen der CVS-Daten (kommt aus einer Excel-Tabelle und der CVS-Export von Excel ist mehr als scheußlich) mit Python einfacher ist. Natürlich kann ich (werde ich vermutlich auch) die Relationships im Command-Line-Tool zusammen bauen, war mir einfach im aktuellen Fall nur zu umständlich und hätte bei der Datenmenge (die SQLite Datei hat ca. 72 kByte) auch nicht viel gebracht. Beim nächsten Projekt kann das schon ganz anders sein.

    Mir ist auch klar - ich habe die Doku von Apple gelesen - dass CoreData keine Datenbank ist, sondern ein Framework, das unter anderem den Umgang mit SQLite deutlich vereinfacht. Auch ist SQLite kein SQL-Light, auch wenn der Name das suggeriert. CoreData soll aber eben doch den Zugriff auf Daten in einer SQLite-DB vereinfachen, also auch den Zugriff auf Tabellen, und Zeilen/Spalten in einer Tabelle - das sind in dem Fall eben die Objektgraphen, CoreData könnte auch viel flexibler eingesetzt werden. Ich bin ja auch damit zurecht gekommen, ohne die Relationships. Ich wollte da einfach nur mal meinen Kommentar zur Eingangsfrage hinterlassen, und dass ich mir das mit den Relationships eben noch genauer anschauen muss. Schon klar, dass ich dafür auch Code schreiben muss - ist mir eh viel lieber, als im IB oder im DataModel rum zu klicken, was oft damit verbunden ist, dass irgendwas nicht so funktioniert, wie man es erwartet.

    Vielleicht - ja nach Datenmenge und Komplexität - ist es für Markus Müller genauso wie bei mir gar nicht notwendig, diese Relationships zu benutzen. Ein passend zusammen gestellter Request ist da manchmal besser als die Arrays der Relationships zu benutzen, die man vorher eventuell erst zusammen bauen muss.

    Ich bin eben eher ein Coder und es ist mir immer alles suspekt, was ohne mein Zutun "out-of-the-box" funktioniert. Ich bin aber dennoch immer offen für andere Alternativen.
  • Muss da nochmal einhaken, nein, CoreData ist eben nicht dafür da, den Zugriff auf eine SQLite-DB zu vereinfachen. CoreData benutzt u.a. sqlite als Storetyp. Das ist aber nur eine von unbegrenzt vielen Möglichkeit, CoreData versteckt all das komplett und es braucht Dich als Entwickler auch überhaupt nicht zu interessieren (es gibt eine API um beliebige eigene Storetypen zu implementieren - gibt ein CodeSample von Apple wo sie einen HTML-Store implementieren).

    Die Relationships sind auch keine Arrays, aber all das steht ja in der Doku...


    What is Core Data?
    The Core Data framework provides generalized and automated solutions to common tasks associated with object life-cycle and object graph management, including persistence. Its features include:

    Built-in management of undo and redo beyond basic text editing
    Automatic validation of property values to ensure that individual values lie within acceptable ranges and that combinations of values make sense
    Change propagation, including maintaining the consistency of relationships among objects
    Grouping, filtering, and organizing data in memory and in the user interface
    Automatic support for storing objects in external data repositories
    Optional integration with Cocoa bindings to support automatic user interface synchronization
  • Du siehst ja gerade an der Bindungsmöglichkeit des zweiten Controllers, dass es sich nicht um eine Datenbank handelt. Es wird ein Objektgraph modelliert. Die Städte "gehören" zu den Ländern. Das sind nicht zwei unabhängige "Tabellen".

    Mit rDBMS hat das wirklich nichts zu tun, auch wenn man das so speichern kann. Man kann es ja auch als XML speichern und es ist dennoch kein XML-Editor. Und man kann es sogar nur im Hauptspeicher ablegen. Es ist dennoch keine RAM-Erweiterung.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Mit dem CoreData-Entity-assists im IB bekomme ich die Städte als Tabelle wenn ich will im Master/Detail-View und es wird gleichzeitig ein Array Controller hergezaubert, dessen MAnagedObjectContext ist an den File's Owner gebunden, modelkeypath: managedObjectContext. Alles klar. Aber wie ziehe ich nun die Verbindung (oder ändere), dass nur die Selektierten angezeigt werden. Muss ich da den Content noch binden, ich habe alles probiert, aber es klappt nie.

    Was mach der Fetch-Button eigentlich, gefetched wird doch automatisch?? ?(
  • twoManyController

    Hallo,

    da ich irgendwie nicht weiter kommen, habe ich das schöne Beispiel von Apple gefunden "twoManyController" gefunden in der Doku.

    Leider ist das MyDocument.xcdatamodel defekt, so dass ich auch hier schwer durchsehe, weil mir das Modell fehlt, hat jemand die Version, die noch funktioniert??




    Gruß fiveyears
  • Hallo,

    nun habe ich es richtig hinbekommen:

    Länder -> Ländercontroller
    Städte -> Städtecontroller

    Ländercontroller hängt an managedObjectContext, Städtecontroller.ContentSet hängt an Ländercontroller.selection.städte , Städtecontroller.ContentArrayForMultipleSelections hängt an Ländercontroller.selection.@distinctUnionOfArrays.städte