2011-09-27 15 views
18

Sto creando un'app e sto provando a utilizzare i dati di base, perché sembra che sia il modo C approvato oggettivo per creare un sistema di archiviazione dati. Il caso d'uso che ho implica relazioni "da molti a molti", come si vedrebbe normalmente in un sistema SQL standard. Comprendo che l'obiettivo C non è un database e funziona in modo diverso. Ho anche rivisto la documentazione qui:Come gestisci e utilizzi le relazioni di base dei dati "da molti a molti"?

http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/CoreData/Articles/cdRelationships.html#//apple_ref/doc/uid/TP40001857-SW10

e molti altri luoghi. Eppure, sto ancora avendo problemi. Qualcuno può spiegarmi cosa faresti se hai un caso d'uso in cui dovresti usare una tabella di riferimenti incrociati SQL? Ad esempio:

Gestori | Dipendenti

Il manager può avere diversi dipendenti, ma i dipendenti potrebbero anche avere più manager. In SQL, vorrei creare una tabella di riferimenti incrociati e quindi utilizzarla.

Esempio: http://www.tomjewett.com/dbdesign/dbdesign.php?page=manymany.php

qualcuno può spiegare come si potrebbe fare che nei dati fondamentali?

Secondo la documentazione dei dati di base, dicono questo:

"si definisce una relazione molti-a-molti con due relazioni a-molti Il primo rapporto a-molti va dalla prima entità al secondo. Entità: la seconda relazione to-molti va dalla seconda entità alla prima entità, quindi si imposta l'inverso dell'altra (se si dispone di uno sfondo nella gestione del database e questo ti preoccupa, non preoccuparti: se si utilizza un negozio SQLite, Core Data crea automaticamente la tabella di join intermedio per te.) "

Ma, oltre a" non essere preoccupato ", non so come questo potrebbe funzionare?

+0

È questo un duplicato di http://stackoverflow.com/questions/1449523/need -help-with-many-to-many-relationships-in-core-data-for-iphone? –

+0

No, perché quel ragazzo fa riferimento a una tabella di join. Da quanto ho letto nei documenti, non è necessario creare una tabella di join? Inoltre, penso che stia chiedendo di recuperare i dati. – Darkenor

risposta

50

Peter: "Ho nove boss, Bob" Bob: "Ripeti?" Peter: "Nove."

Estrarre il cervello dal database. Non chiedere come accedere a una tabella di riferimenti incrociati. Chiedi come trovare i dipendenti per un manager o i dirigenti per un dipendente.

Se si utilizza una sottoclasse personalizzata di NSManagedObject, è possibile dichiarare le proprietà come documentate. Poi si può semplicemente dire:

NSSet *mgrsEmployees = mgr.employees; 
NSSet *employeesMgrs = employee.managers; 

che non vi darà tutti i dipendenti e tutti i dirigenti, solo tutti i dipendenti per quel manager e tutti i dirigenti per quella dipendente. Per cambiare le relazioni:

[mgr addEmployeesObject:newEmployee]; 
[newEmployee addManagersObject:mgr]; // not necessary, automatic if you define inverse 

[mgr removeEmployeesObject:transferredEmployee]; 
[transferredEmployee removeManagersObject:mgr]; // not necessary 
[newMgr addEmployeesObject:transferredEmployee]; 
[transferredEmployee addManagersObject:newMgr]; // not necessary 

Hai solo bisogno di fare uno di ogni coppia di affermazioni, che verrà implicitamente fare gli altri, dirigenti e dipendenti a condizione che avete definito come inverse l'una dell'altra.

Se non si utilizza una sottoclasse personalizzata, l'accesso è un po 'più prolisso

NSSet *mgrsEmployees = [mgr valueForKey:@"employees"]; 
NSSet *employeesMgrs = [employee valueForKey:@"managers"]; 

NSMutableSet *changeMgrsEmployees = [mgr mutableSetValueForKey:@"employees"]; 
[changeMgrsEmployees addObject:newEmployee]; 
// not necessary 
NSMutableSet *changeEmployeesMgrs = [employee mutableSetValueForKey:@"managers"]; 
[changeEmployeesMgrs addObject:mgr]; 

Ecc

+5

Questa è una delle migliori risposte che abbia mai visto sullo stack overflow. Grazie mille! Praticamente mi sono venute le lacrime agli occhi, ero così confuso su questo. – Darkenor

+0

D'accordo, ottima risposta. –

+2

Otto boss ... Otto, Bob. – meggar

1

La risposta semplice è contrassegnare la relazione come una a molte da entrambe le estremità quando si impostano i dati principali in xCode. Questo in sostanza crea molti a molti. È nei documenti Apple da qualche parte, ma non riesco a trovare l'URL.

+0

Ma, eh - come faccio a sapere quali dipendenti hanno manager e quali manager hanno dipendenti? Voglio dire, sarebbero solo una grande lista altrimenti? – Darkenor

+0

Direi employee.managers per ottenere un set di manager per il dipendente. Da un manager diresti semplicemente manager.employees e ottieni un set di tutte le entità dipendenti per quel manager. ("dipendente" e "gestore" sono entrambe istanze specifiche di un'entità che si riferiscono a una persona). –

4

Se la tua domanda è "come puoi farlo nei dati principali", la risposta è esattamente come descrivi. Crea una relazione to-many in ogni entità e definisci ciascuna come l'inverso dell'altro.

Se la tua domanda è "come potrebbe funzionare?", Potresti trovare utile consultare il database sqlite creato dal tuo modello per vedere come imposta le cose. CoreData è abbastanza bravo a farlo, quindi non dovresti preoccuparti dei dettagli, ma se insisti a capire i dettagli non c'è nulla che ti impedisca di guardare i dati per vedere cosa sta facendo.

Una volta posizionato, si attraverserà la relazione come necessario per ottenere gli attributi desiderati. Puoi farlo in codice usando le istanze di NSManagedObject. Per esempio:

NSManagedObject *manager = // get a reference to a manager here 
NSSet *employees = [manager valueForKey:@"employees"]; 
for (NSManagedObject *employee in employees) { 
    NSString *employeeName = [employee valueForKey:@"name"]; 
    // Do whatever else you want here 
} 

Questo esempio può essere semplificata utilizzando l'accesso alle proprietà diretta piuttosto che la sintassi KVO, ma si ottiene l'idea.

Se si desidera attraversare questa relazione molti-a-molti più direttamente come parte di una query di recupero, è possibile eseguire alcune operazioni con i predicati per ottenere ciò che si desidera.Fare riferimento a Apple's predicate programming guide per esempi di cosa è possibile inserire in un predicato

+0

Bene, sapere come funziona va bene, ma quello che voglio veramente sapere è come accedere alla tabella di riferimento incrociata? Voglio dire, in quale altro modo dovresti effettivamente mappare le due entità l'una all'altra? Un attributo di un'entità non ha tutti gli attributi dell'altra entità. – Darkenor

+0

Ho aggiornato la risposta un po 'per includere un esempio di accesso ai dati con riferimenti incrociati utilizzando il codice. Se stai cercando un esempio di un tipo specifico di query, ti preghiamo di chiarire che cosa stai cercando e potremmo eventualmente fornire un predicato che puoi utilizzare per ottenere ciò che desideri. –

0

Probabilmente ciò su cui si è bloccati è come ottenere dall'ambito del modello di dati astratti a un insieme di oggetti che si utilizzano nel codice. Se è così, considerare di usare mogenerator:

http://rentzsch.github.com/mogenerator/

Questa è un'utility a riga di comando (non so come funziona bene l'integrazione XCode in questi giorni), dove si punta a un modello, e ti dà insiemi di oggetti dati Puoi usare. È necessario avere un nome oggetto impostato per ciascuna entità oltre al nome dell'entità.

Gli oggetti dati generati hanno chiamate come employee.managers, che forniscono un insieme di entità Manager per un dipendente e viceversa.

2

Supponiamo di avere due entità nel database, dipendenti e manager. Avrebbero simile a questo nel codice:

@interface Employee : NSManagedObject 
{ 

} 

@property (nonatomic, retain) NSNumber * id; 
@property (nonatomic, retain) NSSet* managers; 

@interface Manager : NSManagedObject 
{ 

} 

@property (nonatomic, retain) NSNumber * id; 
@property (nonatomic, retain) NSSet* employees; 

Quindi diciamo che si voleva recuperare tutti i dipendenti per numero di manager 1, si sarebbe solo avere per ottenere il gestore di oggetti dal database:

NSNumber *managerID = [NSNumber numberWithInt:1]; 
NSEntityDescription * entityDescription = [NSEntityDescription entityForName:@"Manager"              inManagedObjectContext:managedObjectContext]; 
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease]; 
[request setEntity:entityDescription]; 
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %d", @"id", managerID]; 
[request setPredicate:predicate]; 
NSArray *array = [managedObjectContext executeFetchRequest:request error:&error]; 
Manager *manager = [array objectAtIndex:0]; 

e allora si avrebbe tutti i suoi dipendenti nella proprietà dipendenti:

NSSet *allHisEmployees = manager.employees; 

sarebbe esattamente la stessa cosa per recuperare i gestori per un determinato dipendente.

spero che cancella le cose

Problemi correlati