Re: Baffling problem with foreign key
Re: Baffling problem with foreign key
- Subject: Re: Baffling problem with foreign key
- From: Gary Teter <email@hidden>
- Date: Wed, 3 Dec 2008 15:39:20 -0800
On Dec 3, 2008, at 12:08 PM, Chuck Hill wrote:
Hi Gary,
Nice to see you around!
I've been lurking. :-)
On Dec 3, 2008, at 10:11 AM, Gary Teter wrote:
This one has had me scratching my head for two days. I have a
situation where I can set a to-one relationship on an eo but the
change to the foreign key is not reflected in the SQL emitted
during saveChanges.
This code works properly in most circumstances, but a customer
found that if you follow a very specific series of otherwise
completely ordinary actions that work perfectly well in any other
context, then at some point EOF gets confused. The object graph no
longer matches what's in the database.
I think the particular sequence of user actions is a red herring,
but they're along the lines of, "Add two products to your cart.
Proceed to checkout. Change shipping address. Remove item from
cart. Proceed to checkout. Change shipping method." (This is the
relationship that becomes borked.) We process tons of orders every
week with this code, so it's not like the shipping method
relationship is simply broken.
It is possible that an EO is getting removed from an EC and then
altered?
No objects are being deleted during these operations as far as I can
tell. Only two new objects (order line items) are being inserted. The
relationship in question is actually two relationships, between three
objects that are already in the database. OrderObject <<--->
DeliveryServiceClass, and OrderObject <<---> ServiceRate. (Setting
the ServiceRate for an order also sets the DeliveryServiceClass.)
This may produce the same bugs that modifying an EO before it has
been inserted cause. I take it you can reproduce this yourself and
that no back tracking or multiple browser windows are involved?
Yes. It's like doing a combo move in a video game. If I vary any of
the steps it does not fail. If I perform the sequence precisely right
it fails. Grr.
It is possible that an EO is getting removed from an EC and re-
inserted?
It is possible that these steps are resulting in an EO in an
unlocked EC getting altered?
Sadly, this is all in the session's default editing context. I'm
pretty sure it's not a locking/unlocking issue because I'd have
noticed that long before now.
I'm pretty sure I've eliminated threading and remote
synchronization as possible culprits (can still duplicate with
those turned off). This is WebObjects 5.3.3.
The following are true when it's failing:
I can repeatedly change the destination object, save changes, and
not see the proper update statement.
If the object has other changes that need saving, an update
statement gets properly generated for those attributes, but not
the changed foreign key.
Logging statements in the setBorkedRelationship(OtherObject value)
method show that the relationship is being set properly.
Overriding snapshot() and changesFromSnapshot() show that during
saveChanges the current snapshot includes the new value, and so
does the snapshot being compared. This is definitely not normal,
usually the snapshot being compared will include the old value, so
that changesFromSnapshot() will indicate the foreign key needs to
be updated.
That really does sound like what I was seeing when modifying an EO
that was not yet in an EC.
I'm reasonably sure that our code doesn't commit that particular sin
anywhere.
Is the only updated data in the snapshot being compared the FK?
That's what it >should< be, but what I'm seeing is that the snapshot
being compared is identical to the object's current snapshot, so EOF
thinks there are no changes that need to be saved. Even though if I
step through with a debugger the object is clearly on the list of
objects which need to be updated.
Now I must be seeing things. If other attributes on the object are
also being changed, they are not showing up as different in the
snapshot being compared. Yet the update statement issued properly
includes those attributes (but not the two FKs).
The other updated values only appear in snapshot()? Is this key
getting propagated from some other object? A mutable value can
also do this, but I can't see you using an mutable FK.
Gah. No mutable FK's. The relationships are modeled like so:
OrderObject:
{
allowsNull = Y;
columnName = serviceRateID;
name = serviceRateID;
prototypeName = id;
},
{
allowsNull = Y;
columnName = deliveryServiceClassID;
name = deliveryServiceClassID;
prototypeName = id;
userInfo = {"_EntityModeler" = {generateSource = NO; }; };
}
...
{
destination = ServiceRate;
isToMany = N;
joinSemantic = EOInnerJoin;
joins = ({destinationAttribute = id; sourceAttribute =
serviceRateID; });
name = serviceRate;
},
{
destination = DeliveryServiceClass;
isToMany = N;
joinSemantic = EOInnerJoin;
joins = ({destinationAttribute = id; sourceAttribute =
deliveryServiceClassID; });
name = deliveryServiceClass;
},
The back-pointing relationships from ServiceRate and
DeliveryServiceClass are modeled but unmarked as class properties.
Hmmmmm.... Now that's odd. What's that generateSource = NO doing in
there? Ah well, taking it out and doing a full clean/build didn't help.
If the foreign key is marked as "use for locking", the update SQL
will properly include the >old< foreign key in the where clause,
but the foreign key column is not in the list of columns being
updated. This is interesting to me because one of my theories was
that somehow the EODatabase's snapshot was getting updated behind
my back somehow to reflect the new value. But this indicates to me
that the committed snapshot does in fact have the correct (old)
value.
Wow. That is odd. That makes it seem as if the problem is local
to that EC.
If I modify a different to-one relationship and save changes, that
change gets reflected properly, and I can then successfully change
the previously borked relationship.
Maybe saving that change resets the internal EC state?
That's my guess, but I don't want to add some hacky thing like
"change this extra relationship for no good reason other than once in
awhile EOF gets confuzzled." The fact that my object graph can get
out of sync with the database seriously scares the hell out of me.
What if it's not just this one specific set of circumstances? Bad
enough that it leads to an order being sent via the wrong delivery
service and ticks off a customer. What if it's happening when I'm
processing credit card transactions or something? Argh.
I must be breaking some EOF commandment but damned if I can figure
out which one.... Suggestions, hints, theories greatly appreciated.
That is the best I can do at this point.
--
The Ent visualization project:
http://wirehose.com/research/entvisualization
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden