Core Data hat doppelte Datensätze(Einträge), wie unique definieren?

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

  • Core Data hat doppelte Datensätze(Einträge), wie unique definieren?

    Hallo Leute,

    ich habe entdeckt, das meine Daten dreifach in die SQLite mit coreData abgelegt werden. Ich kann das noch nicht so richtig nachvollziehen, warum das kommt.
    Jedenfalls möchte ich eine Entity als unique definieren, sodass doppelte Einträge nicht existieren können.
    Wie kann man einer Entity in core Data als Attribut Unique zuweisen?

    Danke im Voraus,
    brush51
  • brush51 schrieb:

    Wie kann man einer Entity in core Data als Attribut Unique zuweisen?

    Gar nicht.
    Core Data nutzt zwar SQLite, um die Daten abzulegen und Core Data unterstützt soweit ich weiß auch Uniques.
    Nichts desto trotz werden in Core Data selten bis nie Objekte doppelt und dreifach abgelegt.

    Nur weil du z.B. 10 Objekte mit gleichem Inhalt hast, heißt das noch lange nicht, dass 10x dasselbe Objekt drin ist.

    Ansonsten: binde den Kontext einfach an ein Set und nicht an ein Array.
    «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
  • Lucas de Vil schrieb:

    brush51 schrieb:

    Wie kann man einer Entity in core Data als Attribut Unique zuweisen?

    Gar nicht.
    Core Data nutzt zwar SQLite, um die Daten abzulegen und Core Data unterstützt soweit ich weiß auch Uniques.
    Nichts desto trotz werden in Core Data selten bis nie Objekte doppelt und dreifach abgelegt.

    Nur weil du z.B. 10 Objekte mit gleichem Inhalt hast, heißt das noch lange nicht, dass 10x dasselbe Objekt drin ist.

    Ansonsten: binde den Kontext einfach an ein Set und nicht an ein Array.

    AFAIK bringen Sets da wenig.
    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"?
  • Amin Negm-Awad schrieb:

    Lucas de Vil schrieb:

    brush51 schrieb:

    Wie kann man einer Entity in core Data als Attribut Unique zuweisen?

    Gar nicht.
    Core Data nutzt zwar SQLite, um die Daten abzulegen und Core Data unterstützt soweit ich weiß auch Uniques.
    Nichts desto trotz werden in Core Data selten bis nie Objekte doppelt und dreifach abgelegt.

    Nur weil du z.B. 10 Objekte mit gleichem Inhalt hast, heißt das noch lange nicht, dass 10x dasselbe Objekt drin ist.

    Ansonsten: binde den Kontext einfach an ein Set und nicht an ein Array.

    AFAIK bringen Sets da wenig.

    Nicht bei 10 Objekten mit gleichem Inhalt. Deshalb 'ansonsten'. ;)
    «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
  • Amin Negm-Awad schrieb:

    Verstehe ich nicht. Worauf bezieht sich das ansonsten? Vor allem in Bezug auf den Kontext?

    Kontext:
    Wenn du x (unterschiedliche) Objekte mit gleichem Inhalt hast, dann ist das Verhindern augenscheinlich mehrfacher Einträge nicht[1] möglich.
    Ansonsten (also: Wenn du x identische Objekte hast) nutze ein Set an Stelle eines Arrays, da NSSet in seiner Standardimplementierung nur eindeutige Objekte aufnimmt.

    1) 'nicht' bezieht sich hier auf simple Boardmittel. Selbstverständlich lassen sich in den Objekten eindeutig vergebene Properties einrichten und an Hand dieser kann dann selektiert werden.
    Nur war zum Entstehungszeitpunkt meines Beitrags nicht klar, dass die Objekte aus einer XML generiert werden und bereits eine eindeutige Eigenschaft 'id' besitzen.

    Die Unterscheidung dessen ist einfacher als beispielsweise die von mehreren Hans Meyer.

    C-Quellcode

    1. Person * hm = [Person personWithName:@"Hans Meyer"];
    2. [mutableCollection addObject:hm];
    3. [mutableCollection addObject:hm];
    4. [mutableCollection addObject:[[hm copy] autorelease]];
    5. [mutableCollection addObject:[[hm copy] autorelease]];
    6. [mutableCollection addObject:hm];
    7. [mutableCollection addObject:[[hm copy] autorelease]];

    Sei mutableCollection ein NSMutableArray, so befinden sich in diesem dann nach Abschluss 6 Hans Meyer.
    Sei mutableCollection ein NSMutableSet, so befinden sich in diesem dann nach Abschluss 4 Hans Meyer.

    Es ist also abschließend zu wiederholen:
    Nur weil du z.B. 10 Objekte mit gleichem Inhalt hast, heißt das noch lange nicht, dass 10x dasselbe Objekt drin ist.
    «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
  • Nabend, ich hatte vor Kurzem ein ähnliches Problem. Ich hatte in awakeFromNib einen Observer für NSManagedObjectContextDidSaveNotification angemeldet und dann Daten in ein MutableSet eingefügt. AwakeFromNib wurde (warum auch immer) mehrfach aufgerufen und so hatte ich dann auf einmal Duplikate in meinem View. Das ist natürlich jetzt bzgl. Deines Problems sehr ins Blaue geraten, aber vielleicht hast Du ja eine ähnliche Konstellation. Ich habe die Anmeldung des Observers in die init gepackt -> läuft..
  • -awakeFromNib wrd jedes Mal durchlaufen, wenn ein Nib geladen wurde, dessen File's Owner die Instanz ist. Dies ist ja auch richtig, da Outlets gesetzt sein könnten.

    Die Entscheidung, ob etwas ins -init gehört oder ins -awakeFromNib hängt davon nicht ab. Ins -init gehört alles, was keinen Bezug zu anderen Objekten aus dem Nib hat. Es ist in letzter Zeit offenbar modern geworden, -awakeFromNib als -init-Ersatz zu benutzen. Das ist falsch. Das ist nicht die Aufgabe von -awakeFromNib.
    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"?
  • Um sicherzugehen, würde ich in der NSManagedObject-Validierung eine Prüfung einbauen, die AUF MODELEBENE prüft, ob es bereits ein anderes MO mit dieser ID gibt. Eine einfache Fetch-Request. Dann sind schon mal "doppelte" MO ausgeschlossen.

    Anderer Aspekt:
    Die Eindeutigkeit eines MO (bzw. dessen ID) ist Bestandteil Deines DATENMODELLS. Um diese Besonderheit dann auch im Datenmodell zu integrieren, würde ich eine eigene MO-Erzeugungsmethode IM DATENMODELL basteln, die auf dem vom API vorgesehene Methode aufsetzt. Diese Methode klärt VORHER, ob ein MO aktualisiert (ID existiert schon) oder angelegt (ID existiert noch nicht) werden muss. Entweder bastelst Du Dir dafür einen eigenen "Datenmodellcontroller", oder Du packst das in die MO-Klassen, die eine eindeutige ID haben, beispielsweise.

    No.
  • Erstmal herzlichen Dank an alle, das hat echt ein Stein ins rollen gebracht :)

    Ok, NSSet statt NSArray, damit es VOR der Dateneinspeisung in coreData keine Doppelten inhalte gibt, richtig?

    Also die Daten in meiner XML kommen jeweils einmal vor, in der XML sind keine Doppelten Einträge.
    Das NSSet anstatt des NSArray zu verwenden verstehe ich ja, allerdings ist ja mein Problem,
    dass die vorherigen Daten in coreData nicht überschrieben werden.
    Das ist wahrscheinlich was du meinst @Lucas de Vil

    Und dann bleibt mir wahrscheinlich deine Methode übrig @norbi.
    Doch wie stelle ich das an. Ich bin nicht so fit mit coreData und habe auch noch nicht ganz so den durchblick.

    Danke,
    brush51
  • brush51 schrieb:

    Erstmal herzlichen Dank an alle, das hat echt ein Stein ins rollen gebracht :)

    Ok, NSSet statt NSArray, damit es VOR der Dateneinspeisung in coreData keine Doppelten inhalte gibt, richtig?

    Wie bereits gesagt: Das wird nicht funktionieren.

    NSSet überprüft das mit isEqual:. Bei MO ist AFAIK isEqual nur so implementiert, dass es auf Identität prüft. Du kannst aber -isEqual: nicht in einer Subklasse überschreiben. Also hilft dir das nichts.

    Übrigens ist das ein generelles Problem. Letztlich ist die Aussage, dass sich in Sets nur Objekte befinden, bei denen jede Kombination mit isEqual: NO liefert, nicht zu halten. In der Doku steht das leider nicht so explizit. Wenn man sich mal dranmacht, alles richtig zu machen, sieht man, dass es nicht gehen kann.

    brush51 schrieb:

    Also die Daten in meiner XML kommen jeweils einmal vor, in der XML sind keine Doppelten Einträge.
    Das NSSet anstatt des NSArray zu verwenden verstehe ich ja, allerdings ist ja mein Problem,
    dass die vorherigen Daten in coreData nicht überschrieben werden.
    Das ist wahrscheinlich was du meinst @Lucas de Vil

    Und dann bleibt mir wahrscheinlich deine Methode übrig @norbi.
    Doch wie stelle ich das an. Ich bin nicht so fit mit coreData und habe auch noch nicht ganz so den durchblick.

    Danke,
    brush51

    Der Vorschlag von norbi ist zwar richtig, jedoch alles andere als leicht zu implementieren. Du musst das ja ständig nachhalten. Ich würde daher wirklich beim Import einen Fetch machen und mir alle IDs in ein Set holen.Aber wirklich die IDs, nicht die MOs. Bei NSString funktioniert nämlich -isEqual:. Wenn du dann einen neuen Datensatz hast, vergleichst du mit containsObject:, ob die entsprechende ID bereits im Set ist.
    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"?