2015-09-01 13 views
16

Ho notato che l'impostazione di PK non è obbligatoria in Realm e può essere semplicemente omessa. Ma nella documentazione si afferma che:Devo definire la chiave primaria per ogni entità in Realm?

Gli indici vengono creati automaticamente per le proprietà della chiave primaria.

E vorrei chiarire alcune questioni:

1) Qual è il valore di default per PK è definita da Realm, se non si assegna da solo. È un hash o altro? (Se non imposto PK e chiamo [MyRealmObject primaryKey] restituisce nil)

2) Se questo PK implicito è indicizzato per impostazione predefinita? Dovrei preoccuparmi di questo, perché se non è indicizzato, vuol dire che influenza le prestazioni generali di questa Entità (ad esempio, il recupero di oggetti)?

3) È buona prassi definire PK ogni volta per ciascuna sottoclasse RLMObject oppure non è necessario per Realm e può semplicemente fare affidamento sulla sua realizzazione interna definita da Realm stesso?

risposta

14

(Disclaimer:. Io lavoro per Realm)

Yep! L'impostazione di una chiave primaria in Realm non è obbligatoria, né necessaria, motivo per cui è completamente a carico dello sviluppatore e dei requisiti dell'app per determinare se è necessario o meno nella loro implementazione.

In risposta alle vostre domande:

1) Non ci sono valori di default; si specifica una delle proprie proprietà come chiave primaria. primaryKey restituisce nil per impostazione predefinita poiché è necessario sovrascriverlo per indicare a Realm quale proprietà si desidera agire come chiave primaria. Alcuni utenti hanno impostato numeri interi come chiavi primarie, ma il più delle volte, utilizzando una stringa UUID è il più comune.

2) Non c'è una chiave primaria implicita. È necessario utilizzare il metodo [RLMObject primaryKey] per indicare esplicitamente quale proprietà è la chiave primaria e POI verrà indicizzata. :)

3) Nella mia esperienza di sviluppo (di tempo libero), di solito trovo che avere una chiave primaria rende molto più facile identificare e gestire oggetti specifici. Ad esempio, se stai passando un oggetto attraverso i thread, puoi semplicemente passare il valore della chiave primaria e usare [RLMObject objectForPrimaryKey:] per recuperare l'oggetto. Ovviamente ciò dipende dai tuoi requisiti di implementazione. Probabilmente non dovresti aggiungere una chiave primaria a meno che non scoprirai che ne hai davvero bisogno.

A titolo di esempio, ecco cosa si dovrebbe aggiungere alla vostra sottoclasse RLMObject se si volesse impostare una stringa UUID come chiave primaria:

@interface MyObject : RLMObject 

@property NSString *uuid; 

@end 

@implementation MyObject 

+ (NSString *)primaryKey 
{ 
    return @"uuid"; 
} 

+ (NSDictionary *)defaultPropertyValues 
{ 
    @{@"uuid": [[NSUUID UUID] UUIDString]}; 
} 

@end 

spero che ha aiutato!

Addendum: Per elaborare alcuni dei commenti riportati di seguito, le chiavi primarie sono esplicitamente necessarie per qualsiasi API di Realm che modifica la loro funzionalità a seconda che un oggetto con la stessa chiave esista già nel database. Ad esempio +[RLMObject createOrUpdateInRealm:] aggiungerà un nuovo oggetto Realm al database se un oggetto con quella chiave primaria non esiste già e aggiornerà semplicemente l'oggetto esistente in caso contrario.

Come tali, in questi casi in cui una chiave primaria è un componente critico della logica successiva, sono necessari. Tuttavia, poiché queste API sono un sottoinsieme dei diversi modi in cui è possibile aggiungere/aggiornare i dati in Realm, se si sceglie di non utilizzarli, non è ancora necessario avere una chiave primaria.

+5

Grazie Tim. Inoltre, non è possibile aggiornare l'oggetto senza PK se si tenta di eseguire il metodo 'addOrUpdateObject:', Realm aumenta ''RLMException', motivo: 'YourClass' non ha una chiave primaria e non può essere aggiornato'' – David

+0

Nessun problema! Oh! In realtà non lo sapevo. Supponevo che fosse solo l'impostazione predefinita di aggiungere oggetti ogni volta se non si definiva una chiave primaria. Grazie per quello! – TiM

+1

Incontrato il commento che @David pubblica, e sono ancora d'accordo, ottengo lo stesso errore. Pertanto, ** devi ** impostare la chiave primaria nel caso in cui sia necessario aggiornare l'oggetto. La tua risposta dovrebbe essere corretta? – Idan

2

Il cavallo è già stato picchiato a morte, ma non ho potuto fare a meno di fare riferimento al codice Reame che genera un'eccezione se un Oggetto Reame viene creato o aggiornato senza avere una chiave primaria.

+ (instancetype)createOrUpdateInRealm:(RLMRealm *)realm withValue:(id)value { 
    // verify primary key 
    RLMObjectSchema *schema = [self sharedSchema]; 
    if (!schema.primaryKeyProperty) { 
     NSString *reason = [NSString stringWithFormat:@"'%@' does not have a primary key and can not be updated", schema.className]; 
     @throw [NSException exceptionWithName:@"RLMExecption" reason:reason userInfo:nil]; 
    } 
    return (RLMObject *)RLMCreateObjectInRealmWithValue(realm, [self className], value, true); 
} 
+0

Per questa particolare chiamata API, sì è richiesta una proprietà chiave primaria. Questo perché per gestire il comportamento di 'create vs update', è necessario avere un meccanismo per dire se questo oggetto esiste già in Realm o no (altrimenti un nuovo oggetto verrà semplicemente aggiunto ogni volta che viene chiamato). Ma questa API non è l'unico modo per aggiungere/modificare dati in Realm e, se non la usi, non hai ancora bisogno di aggiungere una chiave primaria al tuo modello a oggetti. :) – TiM

+0

Sì, questo ha un senso. Grazie @TiM. –

Problemi correlati