One-To-Many Relationship

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • One-To-Many Relationship

    Hallo! Ich möchte mich gleich vorab für die möglicherweise blöde Frage entschuldigen, aber ich bin noch neu in Cocoa und es treibt mich stellenweise zur Verzweiflung!
    Folgendes Problem: Ich habe eine Anwendung mit CoreData und eine Entität Share. Weiters habe ich einen NSArrayController der an den ManagedObjectContext gebunden ist und eine NSTableView, deren Spalten an die Eigenschaften der Entität Share gebunden sind. So weit, so simpel.
    Für einige Berechnungen in Share ist es notwendig, über alle im Context vorhandenen Shares zu iterieren.
    Wie stell ich das am besten an?
    • In der Klasse Share eine Methode wie diese

      Quellcode

      1. -(NSNumber*)calculateSomeValue(NSArray*)shares;

      zu implementieren verbietet sich, da ich im IB keine Parameter angeben kann (oder doch?)
    • Eine Eigenschaft Shares in der Klasse Share zu implementieren, die ich beim Hinzufügen zum Context mittels FetchRequest setze, geht auch nicht, da der FetchRequest ein Proxy-Array liefert.
    • Eine One-To-Many-Relation auf sich selbst? Geht so was? Und wenn ja - wie?
    Ich laborier schon eine Weile an dem Problem herum aber finde einfach keine zufriedenstellende Lösung...
    Bitte um Hilfe
  • Wenn du unabhängig des selektierten Objektes durchiterieren willst, dann solltest du einen FetchRequest nutzen.
    Das liefert dir dann sicherlich ein Array von Objekten, aber mit denen kannst du dann ja arbeiten.

    1:n Beziehungen auf das Objekt selbst gehen ebenfalls und werden so auch zum Beispiel im NSTreeController (gibt's den überhaupt noch?) genutzt.
    Du gibst ihm einfach zwei Relationships, verbindest beide auf sich und legst eine Invers-Beziehung an. Also ganz normal halt.

    Wenn du einen Satz von Shares hast, der veränderlich ist - aber halt nicht alle Shares brauchst - dann solltest du ein Hauptobjekt 'ShareHolder' erstellen und diesem eine 1:n Beziehung für die Shares geben.
    Dann kannst du in der Subklasse von NSManagedObject, von der dein ShareHolder erbt, eine Methode -calculateSomeValue implementieren, welche dann die Shares aus der Relationship holt.

    Es hängt also davon ab, was genau du machen willst. :)
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Jadidei schrieb:

    Hallo! Ich möchte mich gleich vorab für die möglicherweise blöde Frage entschuldigen, aber ich bin noch neu in Cocoa und es treibt mich stellenweise zur Verzweiflung!
    Folgendes Problem: Ich habe eine Anwendung mit CoreData und eine Entität Share. Weiters habe ich einen NSArrayController der an den ManagedObjectContext gebunden ist und eine NSTableView, deren Spalten an die Eigenschaften der Entität Share gebunden sind. So weit, so simpel.
    Für einige Berechnungen in Share ist es notwendig, über alle im Context vorhandenen Shares zu iterieren.
    Wie stell ich das am besten an?
    • In der Klasse Share eine Methode wie diese

      Quellcode

      1. -(NSNumber*)calculateSomeValue(NSArray*)shares;

      zu implementieren verbietet sich, da ich im IB keine Parameter angeben kann (oder doch?)
    • Eine Eigenschaft Shares in der Klasse Share zu implementieren, die ich beim Hinzufügen zum Context mittels FetchRequest setze, geht auch nicht, da der FetchRequest ein Proxy-Array liefert.
    • Eine One-To-Many-Relation auf sich selbst? Geht so was? Und wenn ja - wie?
    Ich laborier schon eine Weile an dem Problem herum aber finde einfach keine zufriedenstellende Lösung...
    Bitte um Hilfe

    Fetch-Request geht. Ob das Proxys sind, interessiert dich reichlich wenig. Es sind übrigens Objekte im Fault und der Fault wird bei Bedarf aufgelöst.

    Alternativ machst du dir ein Outlet auf den Array-Controller und fragst den nach den Arranged-Objects.
    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"?
  • Ja, die Iteration soll unabhängig vom selektierten Objekt möglich sein.
    Das mit dem FetchRequest habe ich folgendermaßen versucht:
    Beim Erzeugen und Hinzufügen einer Share zum Context führe ich den FetchRequest aus und weise das der Eigenschaft (z.B. shares) hinzu. Da das aber ein Proxy ist, stimmt die Berechnung nicht, da jedes vorhergehende Objekt nicht mehr über die später hinzugefügten Informiert wird. Also das erste Objekt kennt 1 Objekt, das zweite 2, das dritte 3 und so weiter...
    Den FetchRequest direkt in der Berechnung selbst auszuführen, hieße jedoch, den FetchRequest im Model zu implementieren, was mir eigentlich nicht gefällt...

    Ein zweiter Versuch ging in die Richtung wie von Dir beschrieben mit einer zweiten Entität. Ich hab zusätzlich zum NSArrayController noch einen NSObjectController ins Dokument gepflanzt hab, den ich an die Entität "Sharesholder" gebunden habe. Das hat aber leider gar nicht funktioniert... (warscheinlich, weil das mit dem ObjektController Blödsinn war). Wie Implementiert man so was korrekt?
    Wie bekomm ich so was in einem Dokument verdrahtet? Also NSArrayController an Entity Share. So weit, so klar. Aber dann? Welches Objekt binde ich - oder besser: welches Objekt representiert meine Entity "Shareholder"?
    Und wie weise ich dann der Share den Shareholder zu?

    Am sympathischten wäre mir die Variante mit der 1:n Beziehung auf das Objekt selbst. Aber welche zwei Relationships soll ich ihm geben? Wieso zwei? Wie bau ich so was auf?
  • In der Tat hat ein Fetch-Request nichts im Model zu suchen. Das ist erst einmal gut.

    Was davor steht ist allerdings recht merkwürdig. Mir scheint da ein generelles Designproblem vorzuliegen. Ich weiß auch nicht, was du mit Proxy in diesem Kontext meinst!?

    Natürlich ändern sich verwiesene Objekte. Es gibt verschiedene Möglichkeiten, damit umzugehen. Sind die die Aggregate der Key-Value-Technologien bekannt?
    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"?
  • Alternativ machst du dir ein Outlet auf den Array-Controller und fragst den nach den Arranged-Objects.
    Auch die Variante hab ich schon versucht. Beim Hinzufügen der Share zum ArrayController wollte ich der Share die arrangedObjects zuweisen.
    Aber da stieß ich auf das Problem, dass ich einer Entity keine Property vom Typ NSArray geben kann.
    Wenn ich die Eigenschaft nur in der von NSManagedObject abgeleiteten Klasse implementiere und nicht in der Entity, dann findet er die Eigenschaft nicht.
    Wenn ich eine Relationship definiert habe und dann die arrangedObjects zugewiesen habe, dann ging das auch nicht (hab jetzt aber leider vergessen, warum das nicht ging...)
    Wie mach ich das richtig?
  • Was davor steht ist allerdings recht merkwürdig. Mir scheint da ein
    generelles Designproblem vorzuliegen. Ich weiß auch nicht, was du mit
    Proxy in diesem Kontext meinst!?
    Ich war der Meinung, ein FetchReuqest erzeugt so was wie eine DeepCopy des NSArray - sprich: ich bekomme jedesmal ein neues Array-Objekt mit Zeiger auf die Objekte. Das würde dann dieses Verhalten erklären.
    Ist das denn nicht so?
  • Jadidei schrieb:

    Was davor steht ist allerdings recht merkwürdig. Mir scheint da ein
    generelles Designproblem vorzuliegen. Ich weiß auch nicht, was du mit
    Proxy in diesem Kontext meinst!?
    Ich war der Meinung, ein FetchReuqest erzeugt so was wie eine DeepCopy des NSArray - sprich: ich bekomme jedesmal ein neues Array-Objekt mit Zeiger auf die Objekte. Das würde dann dieses Verhalten erklären.
    Ist das denn nicht so?

    Batürlich bekommst du jedesmal eine neue Instanz von NSArray. Das sollte dich allerdings reichlich wenig stören.
    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"?
  • Batürlich bekommst du jedesmal eine neue Instanz von NSArray. Das sollte dich allerdings reichlich wenig stören.
    Das stört mich dahingehend, dass ich dann eben beim ersten Objekt ein NSArray mit count == 1, beim zweiten mit count == 2 und so weiter bekomme.
    Ist ja auch klar - schließlich war beim ersten Fetch ja nur ein Objekt enthalten und beim zweiten dann schon zwei.
    Aber das hieße, ich müsste bei jedem Hinzufügen eines Share-Objekts alle Share-Objekte durchiterieren und die Shares-Eigenschaft neu setzen...
    Das kann's doch nicht sein.
  • Du sollst das nicht in einer Eigenschaft haben. Böser Junge!

    Wenn du eine To-Many-Relationship hast, so ist die Kardinalität der To-Many-Relationship bereits die Count-Eigenschaft. Wenn du das noch einmal in einer gesonderten Eigenschaft modellierst, hast du informationstechnisch zwei Eigenschaften. Die musst du synchron halten, was nicht immer einfach ist.

    Fällt dir gerade auf …
    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"?
  • Du sollst das nicht in einer Eigenschaft haben. Böser Junge!

    Du siehst mich reumütig, mein Haupt in Demut gesenkt!

    Äh - sollte ich vielleicht den Fetch auf die Relation anwenden... Ja. vermutlich sollte ich das tun.
    Also noch mal ganz blöd gefragt (ich kann das erst am Abend am lebenden Objekt ausprobieren): wenn ich auf eine Relation einen Fetch ausführe, ist die dann auch korrekt, wenn ich weitere Objekte hinzu füge? Oder anders gefragt: hat jede Share die ganze Anzahl Shares, unabhängig davon, wann Sie hinzugefügt wurde?
  • Jadidei schrieb:

    Du sollst das nicht in einer Eigenschaft haben. Böser Junge!

    Du siehst mich reumütig, mein Haupt in Demut gesenkt!

    Äh - sollte ich vielleicht den Fetch auf die Relation anwenden... Ja. vermutlich sollte ich das tun.
    Also noch mal ganz blöd gefragt (ich kann das erst am Abend am lebenden Objekt ausprobieren): wenn ich auf eine Relation einen Fetch ausführe, ist die dann auch korrekt, wenn ich weitere Objekte hinzu füge? Oder anders gefragt: hat jede Share die ganze Anzahl Shares, unabhängig davon, wann Sie hinzugefügt wurde?

    Du brauchst keinen Fetch, um Relationships aufzulösen.
    relatedIrgendwas = [relatingIrgendwas valueForKey:@"relationship"];
    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"?
  • relatedIrgendwas = [relatingIrgendwas valueForKey:@"relationship"];
    Genau das ist's, wo ich meine Birne nicht herum bekomme!

    Um das noch mal aufzudröseln:
    Ich hab meine Entity Share. Diese hat eine 1-to-many-Ralation zu Share (Also eine 1:n Beziehung auf sich selbst - wobei ihr mir leider noch nicht gesagt habt, wie das geht).
    So. Ich erzeuge mir diese Entity und füg sie dem Context hinzu.
    Und dann? Woher soll denn die Relation wissen, auf welche Objekte sie sich bezieht? Die ist dann einfach NULL.
    Kannst Du das bitte mal etwas konkret machen...
  • 1. Reflexivverknüpfungen machst du wie alle anderen.

    2. Du erzeugst eine Instanz im Kontext. Die liegt dann darum. Wenn du sie der Beziehung einer anderen Instanz hinzufügen möchtest, machst du das so:

    Quellcode

    1. relatingInstance = …
    2. relatedInstance = …
    3. NSMutableSet *relationship = [relatingInstance mutableSetValueForKey:"relationship"];
    4. [relationship addObject:relatedInstance];


    Aber ehrlich gesagt steht das alles in der Doku.
    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"?
  • In Apples CoreData-Doku?
    Da kommt ganz am Anfang eine Textstelle, die da heißt:
    simply reading from start to finish is not a good strategy for learning how to use the technology effectively.
    Da hab ich wohl diesen Teil weg gelassen... :whistling:

    Aber wenn das jetzt so klappt wie von Dir beschrieben dann hab ich endlich ein Erfolgserlebnis, kann endlich mein Projekt weiter führen, bin überglücklich und gelobe zukünftige Besserung!
    Wie bereits erwähnt: ich kann erst abends versuchen, das umzusetzen aber dennoch schon einmal danke.

    Aber eine Frage hätte ich trotzdem noch: mich würde auch interessieren, wie ich das ohne zweite Entität schaffe. Denn für die Programmlogik brauche ich die nicht...
    Also in der Share-Entität eine Referenz über alle Share-Objekte im Context.
  • Ich verstehe immer noch nicht warum du diese Referenz auf alle Objekte
    in einem Objekt brauchst. Kannst du mir das bitte mal genauer erklaeren?

    Um Berechnungen durchzuführen, die meines erachtens in die Entität "Share" gehören. Um diese Berechnungen durchführen zu können, muss ich über alle Shares im Context iterieren können.