Klucz podstawowy danych podstawowych


81

Może się to wydawać głupie, ale nadal nie mogłem wymyślić, jak oznaczyć atrybut jako klucz podstawowy w pliku xcdatamodel. Moja pamięć trwała to plik sqlite. Czy ktoś może mi pomóc?

W takim przypadku, jak mogę „sprawdzić”, czy identyfikator jest unikalny? Powinienem napisać metodę walidacji czy coś?

Odpowiedzi:


92

Twoje opcje to:

  • Użyj -[NSManagedObject objectID]. Zauważ, że ten identyfikator jest tymczasowy, dopóki obiekt nie zostanie zapisany po raz pierwszy lub nie zadzwonisz-[NSManagedObjectContext obtainPermanentIDsForObjects:error:]
  • Użyj CFUUIDrodziny funkcji, aby wygenerować identyfikator UUID dla każdego obiektu w -awakeFromInsertmetodzie
  • Utwórz własny system przypominający klucz podstawowy, który przechowuje liczbę całkowitą w modelu i zwiększa ją wraz z tworzeniem każdego obiektu

Nie ma dobrego sposobu sprawdzenia, czy właściwość jest unikalna. Najlepszym rozwiązaniem jest upewnienie się, że jest on unikalny w czasie tworzenia, a następnie zaimplementowanie niestandardowej metody ustawiającej, która powstrzyma każdego przed zmianą identyfikatora.


5
O wiele bardziej konstruktywna odpowiedź - powinieneś zostać oznaczony jako rozwiązanie!
Grouchal,

1
Generowanie UUID to najlepszy sposób. Używamy go w naszej aplikacji i działa bardzo dobrze.
obiekt2.0

46

Należy pamiętać, że Core Data jest strukturą trwałości grafów obiektów, a nie bazą danych. Rzeczy takie jak klucze podstawowe są abstrakcyjne, ponieważ zależą od implementacji magazynu trwałego.


2
To powinna być odpowiedź, którą @Mugunth powinien wybrać! Dziękuję za wgląd.
Leonard

czy więc Core Data samodzielnie wygeneruje klucz podstawowy?
Następny programista

24

Dane podstawowe tworzą własny klucz podstawowy - nie musisz go dodawać. Możesz go odzyskać za pomocą

NSManagedObjectID *moID = [managedObject objectID];

14

czasami podczas hakowania potrzebny jest faktyczny int klucza podstawowego. oto jak można to złapać:

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

pomimo tego, że CoreData jest grafem obiektowym, jeśli spojrzy się na dane bazy danych SQLite wygenerowane przez CoreData, ten sposób przechwycenia klucza podstawowego NSManagedObject nie powinien stanowić problemu. ii użyłem CoreData i niskopoziomowej biblioteki sqlite3 C razem w tym samym kodzie, a przekazywanie kluczy podstawowych z CoreData do sqlite3 w celu pobrania rekordów działa dobrze.

! Jeśli zamierzasz używać tego kodu w środowisku produkcyjnym, pamiętaj o możliwych zmianach wewnętrznych w sposobie, w jaki klucz podstawowy db przekształca się w prezentację URIR, może to spowodować uszkodzenie Twojego kodu.

cieszyć się


1
Nie zdefiniowano relacji między identyfikatorem obiektu a identyfikatorem RID programu SQLite. Może być użyteczny jako klucz tymczasowy tylko dla określonej wersji, ale niewłaściwe podejście do trwałego klucza podstawowego, ponieważ może zostać po cichu uszkodzony w innej wersji.
eonil

co dokładnie miałeś na myśli mówiąc „zepsuty w innej wersji”? dlaczego klucze podstawowe powinny się zmieniać?
manitu

Wartości PK nie zostaną zmienione, ale algorytm reprezentujący URL może ulec zmianie, ponieważ żaden algorytm nie jest oficjalnie zdefiniowany. W takim przypadku twój kod nie gwarantuje wyodrębnienia prawidłowej wartości PK. (jeśli masz jakieś źródło definiujące algorytm, daj mi znać, wtedy
polecę

1
DOBRZE. czasami, gdy hakowanie części jest przekonujące. Mój głos przeciwny jest obecnie zablokowany, więc dokonaj pewnych zmian, a ja usunę głos przeciwny.
eonil

2
Ze względu na szybkość i skuteczność, sql jest czasem dobrym rozwiązaniem. Mój przykład, kwerenda zawierająca liczbę (*), sumy, średnie i grupy. To BÓL do zrobienia w OO, jedna linia dla sql! Ten „hack” działa doskonale i jeśli Apple to zmieni, cóż, nadal będą musieli w jakiś sposób sprawić, by sql join działały, więc myślę, że przez chwilę będziemy w porządku;). Głosuj ZA, nawet jeśli teoretycznie nie powinniśmy tego robić. Całkowite ukrycie DB jest moim zdaniem błędem wynikającym bardziej z zasad niż z rzeczywistych przyczyn technicznych. Robimy to, pobieramy partie przez SQL. cały czas w wielu innych systemach, nawet jeśli dostępna jest struktura.
Eric Giguere

0

Bez hakowania NSManagedObjectID możesz przeprowadzić szybkie sprawdzenie atrybutu przed zarządzaniem zdalnym gromadzeniem danych.

Zrobiłem metodę użytkową, sprawdź to tutaj


0

Szybkie rozszerzenie do pobierania klucza podstawowego

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

I dla String

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

-3

Wolałbym raczej użyć Time + the Class name jako unikalnego identyfikatora.


2
Niezbyt polecane, kiedy możesz zagwarantować, że nie zostanie utworzony więcej niż jeden obiekt w tym samym czasie?
fat32

Nie polecam też. Ta metoda nie gwarantuje, że klucz jest unikalny.
Cody,

@Fynh Nie opublikowałem kodu i mój post może być niekompletny, zawsze synchronizuję metodę pobierania czasu.
infiniteLoop
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.