Re: Core Data warning: to-many relation does not have an inverse
Re: Core Data warning: to-many relation does not have an inverse
- Subject: Re: Core Data warning: to-many relation does not have an inverse
- From: Nathan Vander Wilt <email@hidden>
- Date: Thu, 11 Dec 2008 16:10:29 -0800
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 (email@hidden)
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:
This email sent to email@hidden