ioscore-data

Why entity cannot have uniqueness constraints with to-one mandatory inverse relationship?


Why entity cannot have uniqueness constraints with to-one mandatory inverse relationship? Having two entities:

property: name

relationship: department (to-one, non-optional)

property: title (unique constraint)

relationship: person (to-many, optional)

Model won't compile in iOS 9, XCode 7.0.1 with misconfigured entity error:

Misconfigured Entity: Entity Department cannot have uniqueness constraints and to-one mandatory inverse relationship Person.department

Update: Question is still relevant in XCode 8.3.1.


Solution

  • Short answer:

    The underlying problem is most likely caused by the sqlite standard. I'm not sure about that. How ever, it's very likely that it is because of the limitations of sqlite. I found some posts on the internet, where people had issues with multiple constraints on one table and thats most likely the reason why the two-table workaround works.

    Long answer:

    It's pretty late, but I hope it helps anyway.

    This occurs when your Entity has an unique constraint and a mandatory relation. I guess it's because of the added unique constraint behaviors in iOS 9.0. However you can solve this in two ways:

    You remove the unique constraint or make the relation optional. You could handle an optional relation in code. But it won't be a nice solution.

    OR

    You can use a workaround. You can have both. You can create a super class having a unique constraint. However this won't work without problems, too.

    Let's you have three entities. A, B and C.

    A is your super class and B is a sub class of A and C is a sub class of A, too. A has an unique constraint on it's property primaryKey. When saving instances of B and C, you can not have a B and C with the same primaryKey. Because CoreData will manage both as A.

    You could change A to have two Properties:

    You can now map your primaryKeys to originalPrimaryKey and when setting the originalPrimaryKey you could set the string primaryKey property to CLASS_NAME.{originalPrimaryKey}. This would allow you to have the behavior, you would expect. But you have to add a workaround for primaryKeys.