2011-09-27 30 views
18

我正在創建一個應用程序並嘗試使用核心數據,因爲它看起來像是Objective-C批准的創建數據存儲系統的方式。我使用的例子涉及「多對多」關係,就像您通常在標準SQL系統中看到的一樣。我明白,目標C不是一個數據庫,而且工作方式不同。我這裏也審議了有關文件:您如何管理和使用「多對多」核心數據關係?

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

和其他一些地方。但是,我仍然遇到麻煩。有人可以向我解釋,如果你有一個用例需要使用SQL交叉引用表,你會怎麼做?例如:

經理|員工

經理可能有幾個員工,但員工也可能有幾個經理。在SQL中,我會創建一個交叉引用表,然後使用它。

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

有人能解釋你如何能做到這一點的核心數據嗎?

根據核心數據文檔,他們這樣說:

「你定義一個多到許多使用兩個一對多的關係,關係的第一個一對多的關係從第一實體進入到第二位。第二對多關係從第二個實體到第一個實體,然後將每個關係設置爲與其他實體相反的關係(如果您有數據庫管理的背景並且這引起您的擔憂,請不要擔心:如果你使用的是SQLite商店,Core Data會自動爲你創建中間連接表。)「

但是,除了」不擔心「之外,我不知道這可能如何工作?

+0

是http://stackoverflow.com/questions/1449523/need的這個副本-help-with-many-to-many-relationships-in-core-data-for-iphone? –

+0

不,因爲那個人引用了一個連接表。從我在文檔中讀到的內容,您不需要創建連接表?此外,我想他是在提取數據。 – Darkenor

回答

50

彼得:「我有9個老闆鮑勃。」 鮑勃:「再說一遍?」 Peter:「Nine」。

把你的大腦帶出數據庫。不要問如何訪問交叉引用表。詢問如何找到經理或員工經理的員工。

如果您使用NSManagedObject的自定義子類,則可以按文檔聲明屬性。然後,你可以簡單地說:

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

這不會給你所有的員工,所有的管理者,只有所有的員工爲經理和該員工的所有管理人員。要更改關係:

[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 

你只需要做的每對報表中的任意一個,它會暗中做其他的,只要你定義了管理者與員工互爲逆。

如果不使用自定義的子類,訪問更多的是有點冗長

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]; 

等等

+5

這是我見過的堆棧溢出的最佳答案之一。非常感謝!我幾乎有眼淚在我眼裏,我對此很困惑。 – Darkenor

+0

同意,真棒回答。 –

+2

八個老闆......八,鮑勃。 – meggar

1

簡單的答案是在xCode中設置核心數據時,將關係標記爲一對多關係。這實質上創造了許多。它位於蘋果文檔的某處,但找不到該URL。

+0

但是,呃 - 我如何看到哪些員工有經理,哪些經理有員工?我的意思是,他們只是一個大名單否則? – Darkenor

+0

您會說employee.managers爲該員工獲得一組經理。從一個經理你可以簡單地說manager.employees併爲該經理獲得一組所有員工實體。 (「員工」和「經理」都是涉及一個人的實體的特定實例)。 –

4

如果你的問題是「你如何在覈心數據中做到這一點」,答案與你描述的完全一樣。在每個實體中創建一個多對多的關係,並將每個關係定義爲另一個的相反關係。

如果您的問題是「這可能如何工作」,您可能會發現查看從您的模型創建的sqlite數據庫以查看它是如何設置的。 CoreData非常擅長創建,所以你不應該關心細節,但是如果你堅持理解細節,沒有什麼能阻止你查看數據,看看它在做什麼。

一旦你有了這個地方,你可以根據需要遍歷關係來獲得你想要的屬性。你可以在使用NSManagedObject實例的代碼中做到這一點。例如:

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 
} 

此示例還可以使用直接屬性訪問而不是KVO語法進行簡化,但您明白了。

如果您希望直接遍歷這個多對多關係作爲獲取查詢的一部分,那麼您可以使用謂詞做一些事情來獲得您想要的結果。請參閱Apple's predicate programming guide以瞭解可以放入謂詞的示例

+0

那麼,知道它是如何工作的很好,但我真正想知道的是如何訪問交叉參考表?我的意思是,你還應該如何將兩個實體映射到另一個實體?來自一個實體的屬性不具有其他實體的每個屬性。 – Darkenor

+0

我更新了一些響應以包含使用代碼訪問交叉引用數據的示例。如果您正在尋找某種特定查詢的示例,請澄清您的需求,我們可能會提供一個可用於實現您想要的謂詞。 –

0

可能您所堅持的是如何從抽象數據模型領域獲取您在代碼中使用的一組對象。如果是這樣,考慮使用mogenerator:

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

這是一個命令行實用程序(不知道Xcode的集成有多好作品,這些天),你點它的一個模型,它可以讓你的數據集對象您可以使用。除了實體名稱之外,還需要爲每個實體設置一個對象名稱。

生成的數據對象具有employee.managers這樣的調用,這會爲您提供員工的一組Manager實體,反之亦然。

2

假設您的數據庫中有兩個實體,員工和經理。他們會看起來像這樣的代碼:

@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; 

所以我們說你想檢索經理1號全體員工,你只需要從數據庫中獲取經理對象:

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]; 

,然後你將有其在員工財產所有員工:

NSSet *allHisEmployees = manager.employees; 

這將是完全一樣的檢索管理者對於一個給定的僱員。

我希望清除的東西了