Sorry if this ends up showing twice, but the original message has been moderator-queued for length since early this morning. Being several steps behind in even *asking* Core Data questions has been frustrating me all day, as I try to press on in no less ignorance than yesterday.

On Dec 11, 2008, at 2:38 AM, Ben Trumbull wrote:
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)
[snip]

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"

I apologize if there was something in my previous message that suggested I thought the warning, and not my model, was wrong. However, I would like to figure out what makes my way the wrong way, and what the right way would be.

I hope that by "corrupt data" in the case of a many-to-many relationship, you mean that if one isn't careful they may end up with a row that links a foreign key from one table to a non-existent key in another. In that case, I am not too worried, unless I should be? I am already managing my object graph and undo management on my own, and mostly need to use Core Data so that when I'm using the SQLite store I don't have to overwrite the entire graph on disk if few or no objects have actually changed. I am willing to improve my model's architecture where it is incompatible, but if Core Data will bail out if I ever try to cross a particular street on my own, I'll need to learn which streets to avoid and why.


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. [snip]

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.


Maybe I need to clarify my model a bit. Just to be clear, all names have been changed to protect the innocent and any resemblance to a real Company with real Employees is unintentional. Perhaps it would help to tweak my example a bit.

The odd thing about my "Company" is that it likes to move "Desks" around. So when an "Employee" comes in for work, he must ask the "Company" where his "Desk" is that morning. There are really three kinds of Employees, "Outgoing", "Current" and "Interesting". In order to be Interesting, an employee must also be Current. The Outgoing Employees still need to be be able to ask the Company where their Desk is, so they can clean their stuff out of the drawers before they say goodbye.

The reason I want to implement "Outgoing" and "Current" as relationships from a "Company" and "Interesting" as a relationship from a separate "Consultant" is for performance and for information hiding. Employees aren't in charge of whether they're Outgoing/Current and don't need to know if they're considered Interesting. Further, the Consultant shouldn't have to know all Employees, just the interesting ones. Organizing it this way also means I have a ready-to-go list of each type, so I don't have to filter down to, say, all "Current" Employees come "payday" (which can be quite frequent and needs to be taken care of quickly).


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.


In my case it is still bad if the Consultant has an Outgoing Employee on its Interesting list, even if that pointer is not dangling (or the foreign key still refers to an existing row). If Core Data can somehow maintain the type of relationships described above, that's great, but I'm comfortable keeping track of this myself so long as Core Data doesn't mind. Bonus points for it not choking on the entire persistent store should I accidentally leave a "leak" or an unused "dangling reference".


[snip]
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.

Can you elaborate a bit on this object graph corruption? I was under the impression that I could just create a heap of objects, string a few of them together myself, and life would be great. However, it seems that Core Data may be way way more particular about the "strings" than I thought. Is Core Data really that particular if I go to add an object to a set, and it can't set a relationship on said object telling it which ONE set it belongs to?

I'm tempted just to chalk all this up to "premature optimization" and get rid of all the other objects and turn Employees into Independent Know-It-Alls and just see how filtering them out when needed goes, but I'd really like to figure out how to implement things like Sets and MapTables (whose performance characteristics I can grasp) in Core Data.

I really do appreciate your help, and thanks for it! I'm just more than a bit nervous that I may be missing something big that Core Data expects to be doing for me that I shouldn't try do myself.

thanks,
-natevw
_______________________________________________

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 arch...@mail-archive.com

Reply via email to