Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you manage and use "Many to many" core data relationships?

I'm creating an app and trying to use core data, because it seems like it's the objective-C approved way to create a data storage system. The use case I have involves "many to many" relationships, like you'd normally see in a standard SQL system. I understand that objective C is not a database and works differently. I've also reviewed the documentation here:

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

And several other places. And yet, I'm still having trouble. Can someone explain to me what you would do if you have a use case where you'd need to use a SQL cross reference table? For example:

Managers | Employees

Manager may have several employees, but the employees might also have several manager. In SQL, I'd create a cross reference table and then use that.

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

Can someone explain how you could do that in Core data?

According to the core data documentation, they say this:

"You define a many-to-many relationship using two to-many relationships. The first to-many relationship goes from the first entity to the second entity. The second to-many relationship goes from the second entity to the first entity. You then set each to be the inverse of the other. (If you have a background in database management and this causes you concern, don't worry: if you use a SQLite store, Core Data automatically creates the intermediate join table for you.)"

But, besides "not being worried," I don't know how this could possibly work?

like image 968
Darkenor Avatar asked Sep 27 '11 16:09

Darkenor


1 Answers

Peter: "I have nine bosses, Bob." Bob: "Say again?" Peter: "Nine."

Take your brain out of the database. Do not ask how to access a cross-reference table. Ask how to find the employees for a manager or the managers for an employee.

If you use a custom subclass of NSManagedObject, you can declare the properties as documented. Then you can simply say:

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

That will not give you all the employees and all the managers, only all the employees for that manager and all the managers for that employee. To change relationships:

[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 

You only need to do either one of each pair of statements, and it will implicitly do the other, provided you have defined managers and employees as inverses of each other.

If you don't use a custom subclass, accessing is a little more verbose

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

Etc.

like image 134
morningstar Avatar answered Sep 20 '22 02:09

morningstar