Consultant.interestingEmployees -- to-many relationship does not
have an inverse: this is an advanced setting (no object can be in
multiple destinations for a specific relationship)

This error doesn't make sense to me. Is it trying to say an object
can only "belong" to one to-many relationship?

It says no object can be in multiple destinations for a specific relationship (no inverse relationship, btw, fully modeled relationships don't have this issue, because they're fully modeled). If you have Department 0->> People (no inverse to many to People) with D1 and D2 being department objects and P1 being a Person, you cannot have both D1->>{ P1 } and D2->> { P1 } If Department had several no inverse to-many relationships to People, like goodPeople and lazyPeople, then P1 could belong once in each across all the Department objects.

It means you cannot pretend your no inverse to-many is like a many-to- many relationship. If you try, you'll corrupt your data, and we told you not to. You explicitly failed to model the part we needed to verify whether or not your schema is correct, so this was as helpful as we could be about your future undefined intentions.

If you sit down and think about how one implements many-to-many relationships in a database, it should be clear why this is the case. If that didn't make sense, then please, just model the inverse like the compiler is suggesting.

"this is an advanced setting" == "if you didn't understand this message, you're going the wrong way. Otherwise, you're probably going the wrong way"

The other problem is that I do want to define an inverse for
Employee.company, but I can't set it to *both*
Company.currentEmployees and .previousEmployees. I think the answer is
to maintain the Employee.company relationship field myself without any
inverse, but then I get two more warnings for each of the Company to-
many relationships.

Why are you trying to solve that problem ? In the obvious case, Employee.company needs to be the inverse for currentEmployees because it's the current company, and the alternatives semantically don't make any sense. Then, previousEmployees has a separate inverse, if only for bookkeeping purposes (e.g. so Core Data maintains everything for you)

If you're trying to model companies and employees having an audit record all of their previous employments, then you need to do that explicitly instead of trying to be too clever. I'd recommend a many- to-many relationship between Employee and Company for "previous employers" to match "previous employees". You could go with "lastPreviousEmployer" and make it a one-to-many.

This model was easy to implement in Foundation, I just created a bunch
of Employee objects and just made sure they were in the proper sets
(current/previous/interesting).

... and they were different sets. What you're trying to do is like having each of the three sets only retain the object once, and promise on the honor system not to hork everything up when any one of the 4 objects is deallocated. Naturally, Foundation doesn't let you perpetuate such a sin upon NSSet, although you are free to hurt yourself like that with CFSet. We split the difference and give you a compiler warning saying we think it's a pretty bad plan for most people most of the time.

I also have a Consultant. It has a to-many relationship to
interestingEmployees. Nobody talking to an Employee needs to have
access to the Consultant, so there is no inverse relationship.

It would probably be better to define that kind of logic on the Objective-C class (NSManagedObject subclass) for the entity. You could have an inverse to-many in the model, but not expose it as public API for your class. A lot of people forget that the Objective- C class doesn't have to resemble the Entity's schema. Data modeling ! = class modeling. There are things you can do much more efficiently with protocols compared to entity inheritance for example.

If you have lots and lots of these objects (many thousands), then you might decide the convenience of the automatic book keeping isn't worth it, and have a no inverse relationship here. However, you will have to be VERY EXTREMELY careful to fix up these relationships on Consultant whenever an Employee is deleted. You'll probably also need to accommodate undo & redo across saves for deleted employees and other scenarios. Depending on usage patterns and deftness of coding you may end up wasting more performance cleaning up the Consultants by hand.

If you don't have many thousands of objects, then just model the inverse and be done with it. If you have 10^4 or more objects then the answer is that it depends, but it's usually easier to start with the inverse and get rid of it later if performance data shows it problematic.

There's no compelling reason why relationships should necessarily have
an inverse (and there's a build setting to turn off the warning now).
You mainly have to be careful that when you delete or insert an
Employee object, you make sure you adjust the non-inversed
relationships to match.

Pretty much everybody screws up maintaining inverse relationships eventually, because it only takes the slightest bug, happening just once, to destroy the object graph persisted in the database and be corrupted thereafter. You correctly maintain by hand all your no inverse relationships when multiple threads resolve an merge conflict while the user is undoing on the main thread, right ? Also, there's no latency between the time you delete a destination object and the time you clean up all the no inverse relationships pointing to it, right ? Asking us to fulfill a fault with the inconsistent state during any latency would be bad. You've done all that faster than the framework optimized code so your time was well spent, right ? And it's surprisingly easy to accidentally violate the next rule when transferring objects between relationships.

Further, no inverse to-many relationships can only be used as de facto implicit one-to-many relationships. You cannot use a no inverse to- many as an implicit many-to-many relationship. If you try, and many people on cocoadev did, thus inspiring the warning for 10.5, you will corrupt your database.

There are some unusual circumstances where this feature is extremely useful, in ways that cannot be easily or efficiently worked around. That is why we don't just remove it entirely.

But if you don't understand why the API contact specifically says *at compile time* (not nestled away in documentation you might not have read, not in a header file, actually enforced by the compiler) that you've signed the liability waiver, then you probably shouldn't be using the feature.

- Ben

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Reply via email to