Joseph Astrahan
Joseph Astrahan

Reputation: 9082

Core Data Relationship For Unidirectional One to Many

What is the best practice for creating Unidirectional One to Many Relationships in Core Data?

For example...

Lets take two classic entity examples, "teacher" and "student".

Each student has one teacher, and each teacher has many students.

In CoreData right now you are forced to provide an inverse such that teacher is forced to have a reference to a 'student'. If you don't you get this nice warning that says something along the lines of...

file:///Users/josephastrahan/Documents/VisualStudioProjects/Swift3WorkOrders/WorkOrders/WorkOrders/WorkOrders.xcdatamodeld/WorkOrders.xcdatamodel/: warning: Misconfigured Property: Teacher.student should have an inverse

What if I don't want teacher to have a reference to student?

Some other posts have brought up that I should just allow the inverse anyways but I think this inverse may be causing an issue with one of my projects.

That said let me explain my exact issue.

Lets say that our teacher has a unique attribute int64 called 'id'. Lets say the students also have unique attribute int64 called 'id'.

The int64 is enforced to be unique by adding a constraint on the model for teacher on id. (refer to image below to see how that is done)

enter image description here

Every year there is new students but the teachers stay the same. So I decided that I want to delete all the students without deleting the reference to the teacher. So I set the delete rule to 'nullify' for the relationship for the teacher to student and 'nullify' for the student to teacher.

Now when I create a new student I want to assign one of the existing teachers to that student... (something like student.teacher = teacher object with id of 1 or the same id as before) however!! , because the teacher has the inverse relationship to a student that no longer exists (which in theory should be null) the program crashes!

I know this is the case as I've used print console logs to narrow it down the exact point that it occurs. Also I know this because if I add the delete rule of cascade for student the crash will go away but...then I lose my teacher! which I don't want...

Some things that I think might be the issue:

1.) When I do my testing I do it at the startup of the program which creates a new context everytime. Could it be that because I never deleted teacher it still thinks it refers to a student from a context that no longer exists? (if I'm even saying this right...)

I'm not sure the best solution to acheive what I'm trying to do with Coredata and any advice is much appreciated!

Note:

Forgot to mention I also have the Merge Policy of: NSMergeByPropertyObjectTrumpMergePolicy, which will overwrite the old data with the new. When I'm creating new students I'm creating new teachers also just using the same id which should follow this policy.

Upvotes: 3

Views: 1013

Answers (2)

Zahid
Zahid

Reputation: 562

Unique Constraints are available with iOS9. Which have helped iOS Developers with adding and updating records in CoreData.

Unique Constraints make sure that records in an Entity are unique by the given fields. But unique constraints along with To-Many relationship leads to a lot of weird issues while resolving conflicts.

e.g. “Dangling reference to an invalid object.”

This post is basically focused to a small problem that may take days to fix.

http://muhammadzahidimran.com/2016/12/08/coredata-unique-constraints-and-to-many-relationship/

Upvotes: 0

Mundi
Mundi

Reputation: 80271

You are almost there.

  1. The advice to keep the inverse relationship is a good one. Keep it.
  2. Your issue is likely caused by different contexts. Instead of holding on to a teacher object in memory, you should fetch the teacher (based on the id) in the context in which you intend to use it.
  3. Your nullified students should not have any impact. A to-many relationship is really a Set<Student>. Make sure the set is empty.

NB:
If you want to keep the student in the database (for historical purposes) - it seems from your description that this is the case - you might also consider another scheme: give your students another attribute (such as a year) and use that to filter the student list. You would not have to delete or nullify anything. You could also do some more interesting time-based queries on the data.

Upvotes: 1

Related Questions