Первинний ключ основних даних


81

Це може здатися дурним, але я все ще не міг зрозуміти, як позначити атрибут як первинний ключ у файлі xcdatamodel. Моє постійне сховище - це файл sqlite. Хто-небудь може мені допомогти?

У такому випадку, як я можу "перевірити" ідентифікатор, щоб бути унікальним? Чи слід писати метод перевірки чи щось інше?

Відповіді:


92

Ваші варіанти:

  • Використовуйте -[NSManagedObject objectID]. Зауважте, що цей ідентифікатор є тимчасовим, доки об’єкт не буде збережено вперше, або ви здійсните дзвінок-[NSManagedObjectContext obtainPermanentIDsForObjects:error:]
  • Використовуйте CFUUIDсімейство функцій для створення UUID для кожного об’єкта у вашому -awakeFromInsertметоді
  • Створіть власну систему, схожу на первинний ключ, яка зберігає ціле число у вашій моделі та збільшує його зі створенням кожного об’єкта

Немає хорошого способу підтвердити, що властивість є унікальною. Найближче, що ви отримаєте, - це переконатися, що він унікальний під час створення, а потім застосувати власний метод встановлення, який зупиняє будь-кого, хто коли-небудь змінює ідентифікатор.


5
Набагато конструктивніша відповідь - вас слід позначити як рішення!
Grouchal

1
Створення UUID - найкращий спосіб. Ми використовуємо його в нашому додатку, і він служить дуже добре.
object2.0

46

Майте на увазі, що Основні дані - це структура збереження об'єктних графіків, а не база даних. Такі речі, як первинні ключі, абстрагуються, оскільки вони залежать від реалізації постійного сховища.


2
Це мала бути відповідь, яку повинен був вибрати @Mugunth! Дякуємо за розуміння.
Леонард

так чи Core Data просто генеруватиме первинний ключ самостійно?
Наступний розробник

24

Основні дані створюють власний первинний ключ - його не потрібно додавати. Ви можете отримати його за допомогою

NSManagedObjectID *moID = [managedObject objectID];

14

іноді при злому потрібен фактичний int первинного ключа. ось як його можна схопити:

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

незважаючи на те, що CoreData є графіком об'єктів, якщо поглянути на дані, створені CoreData, що містять базу даних SQLite, такий спосіб захоплення первинного ключа NSManagedObject не повинен становити проблему. ii використовували CoreData та низькорівневу бібліотеку sqlite3 C разом в одному коді, і передача первинних ключів від CoreData до sqlite3 для отримання записів працює чудово.

! якщо ви маєте намір використовувати цей код у виробництві, знайте про можливі внутрішні зміни в способі перетворення первинного ключа db на презентацію URIRe, це може гальмувати ваш код.

насолоджуватися


1
Не визначено жодного зв’язку між ідентифікатором об’єкта та SQLite RID. Може бути використаний для тимчасового ключа лише для певної версії, але неправильний підхід для постійного первинного ключа, оскільки його можна безшумно зламати в іншій версії.
eonil

що саме ви мали на увазі під словом "розбита в іншій версії"? чому первинні ключі повинні змінюватися?
manitu

Значення PK не будуть змінені, але алгоритм, який робить представлення URL-адреси, може бути змінений, оскільки жоден алгоритм не визначений офіційно. І в цьому випадку ваш код не гарантує отримання дійсного значення ПК. (якщо у вас є джерело, яке визначає алгоритм, дайте мені знати, тоді я порекомендую вам опублікувати)
eonil

1
ГАРАЗД. іноді при злому частина переконлива. Наразі моє голосування проти заблоковано, тож ви внесете певні зміни, і я видалю цей голос.
eonil

2
Заради швидкості та ефективності sql іноді є найкращим способом. Мій приклад: кількість запитів (*), суми, середні показники та групи. Це БІЛЬ, щоб зробити в OO, один рядок для sql! Цей "хак" працює ідеально, і якщо Apple змінить його, ну, їм все одно доведеться як-небудь змусити sql приєднатися, так що я думаю, що ми на деякий час в порядку;). Голосуйте за, навіть якщо теоретично ми не повинні цього робити. На мою думку, повністю приховувати БД - це помилка, яка скоріше базується на принципах, ніж на реальних технічних причинах. Ми робимо це, отримуємо пакети за допомогою SQL. весь час у багатьох інших системах, навіть якщо фреймворк доступний.
Eric Giguere


0

Швидке розширення для отримання первинного ключа

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

І для Струнного

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

-3

Я б скоріше використовував Time + ім'я класу як унікальний ідентифікатор.


2
Не дуже рекомендується, коли ви можете гарантувати, що одночасно створюється не більше одного об'єкта?
fat32

Не рекомендується також. Цей метод не може гарантувати, що ключ унікальний.
Коді

@Fynh Я не розмістив код, і, можливо, мій пост є неповним, хоча я завжди синхронізую метод отримання часу.
infiniteLoop
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.