Re: Dangling reference across non-ClassProperty relation
Re: Dangling reference across non-ClassProperty relation
- Subject: Re: Dangling reference across non-ClassProperty relation
- From: Kasper Frederiksen <email@hidden>
- Date: Fri, 5 Nov 2010 16:06:59 +0100
Hi Chuck,
On Thu, Nov 4, 2010 at 5:45 PM, Chuck Hill <email@hidden> wrote:
>
> Hi Kaspar,
>
> On Nov 4, 2010, at 5:08 AM, Kasper Frederiksen wrote:
>
> > I have a referential integrity problem in my model and I am at a loss as to how to debug this.
> >
> > To illustrate the problem in it's simplest form, I have made a model containing two entities: User and Ticket. User has a ticket foreign key (ticketFK) entity and a to-one relationship that maps User.ticketFK to a Tiket primary key (ticketID).
>
> Can you switch this? Have Ticket.userFK as the relationship join? That would result in a user.tickets() relationship in EOF.
>
You posed an interesting question here, so I spent some time exploring
this option:
I removed the to-one relationship user.ticket() from User.ticektFK to
Ticket.ticketID and added the relationship user.tickets() from
User.userID to Ticket.userFK. This meant that I needed to add the
attribute Ticket.userFK. To fill out this new attribute I removed the
old ticket.user() relation (Ticket.ticketID --> User.ticketFK) and
replaced it with: Ticket.userFK --> User.iserID.
Now there is no longer a need to have User.ticketFK, so I deleted this
attribute along with the row in the database table.
Now running the test again, of course the database ends up in a
consistent state since the troublesome column User.ticketFK no longer
exists.
The reference from Ticket to User is no longer public (it is not a
class property). But it is not a complete success, because of the
following:
1) fetch a User in to editing context A.
2) add to this user three tickets in editing context A.
3) localize one of the tickets in to editing context B, delete it
and save editing context B.
4) back in editing context A, read the relation User.tickets and
print out the contents of the array.
... it turns out that the user in editing context A still has three
tickets in step 4.
Remember, this was all done with the relation
Ticket.userFK-->User.userID NOT being a class property. If I change
this relation to a class property (writing Ticket.setUser() and
Ticket.getUser() along the way), THEN step 4 will report that the user
has two tickets ...and we are back where we started :)
>
> > Tickets may become invalid, then this happens they are deleted. This will typically happen in a separate editing context from the one containing the User. To avoid users referencing a Ticket that does not exist I make a relation from Ticket.ticketID to User.ticketFK and set the delete rule to 'nullify'.
> >
> > There is no need for the business code to reference the user through the ticket, so I do not mark the relation from Ticket to User as a class property.
> >
> > To test, I fetch a User and follow the relation to get the User's Ticket. Then I localize this Ticket in to a new editing context, delete the local Ticket and save the new editing context. I the database the ticket row is gone. The User object still refers to the ticket -this can't be helped, it is seeing cache. The problem is this: the User row in the database still has ticketFK set! It is pointing to a Ticket row that does not exist. Saving the Users editing context or termination the application does not change this.
>
> Using the modeling above will still leave you with the User referring to the deleted ticket unless you have a delete rule from Ticket to User. However this won't be in the database and won't "stick".
I am not sure I see your point. I agree that a delete rule ('nullify')
from Ticket to User is necessary. It seems that the change does
"stick", but only if the reference from Ticket to User is a class
property (eg. public).
>
> >
> > Does some one have any suggestions as to how I debug why the 'nullify' rule on the Ticket-->User relation does not work?
> >
> > Here are some of my further observations on the problem:
> > ---
> > No User update SQL is sent to the database, only the delete for the Ticket row.
> >
> > I have tried changing the Ticket-->User relation to a class property. Since the destination is not a primary key, WO now insists the relation be modeled as to-many. I also write the getter and setter for the Users on the Ticket. Now the above example works perfectly! The price I had to pay, is an additional getter and setter in the business API. I would very much like to avoid this since no business rule will ever need them and it is just cluttering up the API.
>
> I think you can remove the methods, EOF will use KVC to get around not having them.
I was using EOCustomObject out of habit (they perform better than
EOGenericRecord), but this is an interesting suggestion. Switching to
EOGenericRecord allows me to simplify my example even further. In my
new test I never wrote a Java implementation for User and Ticket, I
simply told the model they where EOGenericRecords and set the
relations using KVC before I saved. Unfortunately I was still able to
recreate all the effects described so far. The relation from Ticket to
User must be a class property for the delete rule to trigger.
>
>
> > I am beginning to suspect that the model defined delete rules are only triggered for relations that are also class properties. Can any one confirm this?
>
> I think this is the case now. I think it was not the case in earlier versions, but I am not sure.
That sounds plausible, one of my older colleagues seems to recall that
this worked "back in the day" :)
We are currently running version 5.3.3.
What version are you using?
Can you remember when this change might have happened?
After this latest round of tests, I am ready to conclude that EOF
references need to be public to trigger the delete rule and will
instead work on a clever way to shield this reference from misuse by
the API programmer. If some one else has a break through, please let
me know.
>
> Chuck
>
>
> > If any one wants to see the test code described above, I'll send you the sample project.
> >
> > Kind regards,
> > -Kasper Frederiksen
> >
> > _______________________________________________
> > 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
>
> --
> Chuck Hill Senior Consultant / VP Development
>
> Practical WebObjects - for developers who want to increase their overall knowledge of WebObjects or who are trying to solve specific problems.
> http://www.global-village.net/products/practical_webobjects
>
>
Thanks.
-Kasper Frederiksen
_______________________________________________
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