Kerndaten-Primärschlüssel


81

Das mag dumm erscheinen, aber ich konnte immer noch nicht herausfinden, wie man ein Attribut als Primärschlüssel in der xcdatamodel-Datei markiert. Mein persistenter Speicher ist eine SQLite-Datei. Kann mir jemand helfen?

Wie kann ich in diesem Fall eine ID als eindeutig "validieren"? Soll ich eine Validierungsmethode schreiben oder so?

Antworten:


91

Ihre Optionen sind:

  • Verwenden Sie -[NSManagedObject objectID]. Beachten Sie, dass diese ID nur vorübergehend ist, bis entweder das Objekt zum ersten Mal gespeichert wird oder Sie anrufen-[NSManagedObjectContext obtainPermanentIDsForObjects:error:]
  • Verwenden Sie die CFUUIDFunktionsfamilie, um eine UUID für jedes Objekt in Ihrer -awakeFromInsertMethode zu generieren
  • Erstellen Sie Ihr eigenes primärschlüsselähnliches System, das eine Ganzzahl in Ihrem Modell speichert und diese bei der Erstellung jedes Objekts erhöht

Es gibt keine gute Möglichkeit, zu überprüfen, ob eine Eigenschaft eindeutig ist. Am nächsten stellen Sie sicher, dass es zum Zeitpunkt der Erstellung eindeutig ist, und implementieren dann eine benutzerdefinierte Setter-Methode, die verhindert, dass jemand jemals die ID ändert.


5
Eine viel konstruktivere Antwort - Sie sollten als Lösung markiert werden!
Grouchal

1
Das Generieren von UUID ist der beste Weg. Wir verwenden es in unserer App und es funktioniert sehr gut.
Objekt 2.0

46

Beachten Sie, dass Core Data ein Objekt-Diagramm-Persistenz-Framework und keine Datenbank ist. Dinge wie Primärschlüssel werden weg abstrahiert, da sie von der Implementierung des persistenten Speichers abhängen.


2
Dies hätte die Antwort sein sollen, die @Mugunth hätte wählen sollen! Vielen Dank für Ihren Einblick.
Leonard

Wird Core Data also nur den Primärschlüssel selbst generieren?
Nächster Entwickler

24

Core Data erstellt einen eigenen Primärschlüssel - Sie müssen keinen hinzufügen. Sie können es mit abrufen

NSManagedObjectID *moID = [managedObject objectID];

14

Manchmal benötigt man beim Hacken das tatsächliche int des Primärschlüssels. Hier ist, wie man es greifen kann:

NSManagedObjectID *yourManagedObjectID = [yourManagedObject objectID];
int yourManagedObject_PK = [[[[[yourManagedObjectID URIRepresentation] absoluteString] lastPathComponent] substringFromIndex:1] intValue];

Obwohl CoreData ein Objektdiagramm ist, sollte diese Art des Abrufs des Primärschlüssels eines NSManagedObject kein Problem sein, wenn man sich die von CoreData generierten SQLite-Datenbankdaten ansieht. Ich habe CoreData und die sqlite3 C-Bibliothek auf niedriger Ebene zusammen im selben Code verwendet und die Übergabe von Primärschlüsseln von CoreData an sqlite3 zum Abrufen von Datensätzen funktioniert einwandfrei.

! Wenn Sie diesen Code in der Produktion verwenden möchten, beachten Sie mögliche interne Änderungen an der Art und Weise, wie der DB-Primärschlüssel in eine URIR-Darstellung umgewandelt wird. Dies kann Ihren Code beschädigen.

genießen


1
Es ist keine Beziehung zwischen Objekt-ID und SQLite-RID definiert. Könnte für temporären Schlüssel nur für eine bestimmte Version verwendet werden, aber für persistenten Primärschlüssel falscher Ansatz, da er bei einer anderen Version stillschweigend beschädigt werden kann.
Eonil

Was genau meintest du mit "kaputt bei anderer Version"? Warum sollten sich Primärschlüssel ändern?
Manitu

PK-Werte werden nicht geändert, aber der Algorithmus zur URL-Darstellung kann geändert werden, da kein Algorithmus offiziell definiert ist. In diesem Fall kann nicht garantiert werden, dass Ihr Code einen gültigen PK-Wert extrahiert. (Wenn Sie eine Quelle haben, die den Algorithmus definiert, lassen Sie es mich wissen, dann werde ich Ihnen das Posten empfehlen)
eonil

1
OK. manchmal, wenn das Hacken eines Teils überzeugend ist. Meine Abwahl ist derzeit gesperrt, daher nehmen Sie einige Änderungen vor. Ich werde die Abwahl entfernen.
Eonil

2
Aus Gründen der Geschwindigkeit und Effektivität ist SQL manchmal der richtige Weg. Mein Beispiel ist eine Abfrage mit Anzahl (*), Summen, Durchschnittswerten und Gruppen. Es ist ein Schmerz in OO zu tun, einzelne Zeile für SQL! Dieser 'Hack' funktioniert perfekt und wenn Apple ihn ändert, müssen sie den SQL-Join trotzdem irgendwie funktionieren lassen, also denke ich, dass wir für eine Weile in Ordnung sind;). Stimmen Sie ab, auch wenn wir dies theoretisch nicht tun sollten. Das vollständige Ausblenden der DB ist meiner Meinung nach ein Fehler, der eher auf Prinzipien als auf realen technischen Gründen beruht. Wir machen das, bekommen Batches von SQL. die ganze Zeit in vielen anderen Systemen, obwohl ein Framework verfügbar ist.
Eric Giguere

0

Ohne NSManagedObjectID zu hacken, können Sie eine schnelle Überprüfung Ihres Attributs durchführen, bevor Sie Ihre Remote-Datenerfassung verwalten.

Ich habe eine Dienstprogrammmethode erstellt. Überprüfen Sie sie hier


0

Eine Swift-Erweiterung zum Abrufen des Primärschlüssels

extension NSManagedObject {
    var primaryKey : String {
        guard objectID.uriRepresentation().lastPathComponent.count > 1 else { return "" }
        return objectID.uriRepresentation().lastPathComponent.substring(from: 1)
    }
}

Und für String

extension String
{
    func substring(from : Int) -> String {
        guard self.count > from else { return "" }
        return String(self[self.index(self.startIndex, offsetBy: from)...])
     }
}

-3

Ich würde lieber Zeit + den Klassennamen als eindeutige Kennung verwenden.


2
Nicht wirklich zu empfehlen, wann können Sie garantieren, dass nicht mehr als ein Objekt gleichzeitig erstellt wird?
Fat32

Auch nicht zu empfehlen. Diese Methode kann nicht garantieren, dass der Schlüssel eindeutig ist.
Cody

@Fynh Ich habe den Code nicht gepostet und mein Beitrag ist möglicherweise unvollständig. Ich synchronisiere immer die Time-Getter-Methode.
infiniteLoop
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.