Re: Pb updating a to-many relationship with refaultAllObjects()
Re: Pb updating a to-many relationship with refaultAllObjects()
- Subject: Re: Pb updating a to-many relationship with refaultAllObjects()
- From: email@hidden
- Date: Mon, 17 Nov 2003 12:17:51 CDT
- Priority: 3 (Normal)
[demime could not interpret encoding binary - treating as plain text]
On Fri, 14 Nov 2003 23:02:03 +0100 Jean Pierre Malrieu wrote:
> But if an item has been added to the to-many relationship by another
> application, calling refaultAllObjects() does not update the list of
> items in my component.
> Is it normal behaviour?
> What is the solution?
This is tricky, and I don't know a good way around it. First we need to
understand how EOF works, and the concept of 'snapshots'. EOF keeps a
'snapshot' for every EOEnterpriseObject (abbreviated "EO"). This snapshot
is basically an NSDictionary of that EO's properties and values. The
snapshots are used for optimistic locking, as well as for purposes of
efficiency. One problem is that these purposes of efficiency will
sometimes get in the way of getting fresh data.
So now let's think about what refaultAllObjects() does. It will turn all
of the EO's currently watched by the given EOEditingContext (EC) into
"faults". This means they no longer contain property values, but next
time a property value is accessed on a given EO, that EO will be
"cleared", and turned back into a full EO with property values. The
problem is that ordinarily, the snapshot values will be used, instead of
a trip to the db, to resolve these property values. So even before we
get to talking about your to-many relationships, refaultAllObjects() may
not do what you want---you may end up with less-than-fresh data, if
another process has changed the values in the db, but the snapshots do
not reflect this.
One way to deal with this problem is by setting the fetch timestamp on
the EC---this fetch timestamp means "don't accept snapshot values from
before this point in time; demand fresh data, and make a trip to the db
if neccesary to get it." Another way is to call refetchAllObjects()
instead of refaultAllObjects(). refetchAllObjects() means "don't just
refault these objects, actually go to the db to get fresh values for all
these objects." That could take a while if you have lots of objects in
the EC, of course. But even with refetchAllObjects(), that will just
refetch objects _currently_ in the EC----objects later put into the EC,
perhaps by following a to-one relationship, may still use old 'snapshot'
data. So you probably want to pay attention to the fetch timestamp.
Now we get to talking about to-many relationships. In addition to the
snapshots kept for an EO, seperate snapshots are kept for to-many
relationships. These to-many snapshots simply record, for a particular
EO, which objects are at the destination of a particular to-many
relationship. But in understanding what's going on, it helps to know
that these are seperate snapshots kept for to-many relationships, they
are not just a part of the EO snapshot.
Now, what's happening for you. You call refaultAllObjects(), but then
when you access an object, it's using the old cached snapshot values for
it's to-many array destinations. Fixing the fetch timestamp _may_ work
to fix this---ideally the EC won't accept those old to-many snapshots
that are too old for it's fetch timestamp, and will demand a trip to the
db to get fresh information. But it's possible this may not work----EOF
unfortunately seems to sometimes forget about to-many snapshots in a lot
of it's functions, kind of leaves them out, which is a bug. But it's
worth a try.
Also, refetchAllObjects() does NOT refetch to-many snapshot information,
you'll get fresh values for all simple properties in your EOs, but even
after calling refetchAllObjects(), the EOs will still be using the
possibly old to-many snapshot information. So that won't work.
You can manually fetch this information by setting up an
EOFetchSpecification with prefetching relationship paths including the
relationships you are interested in, and with
setRefreshesRefetchedObjects(true). That will definitely work, but it's
a pain---and for some types of relationships (like many of those that go
from one model to another)---EOF won't let you prefetch relationships.
Ben Trumbull has also suggested that you can manually set the to-many
snapshot to "null" when you refault your EOs, and then, when the EO's
need to re-load to-many destination information, there's no old snapshot
there, and EOF will go to the db to get the values. I haven't tried this
yet myself. I am at the moment very nervous about doing anything unusual
with the EOF stack, since I'm in the middle of trying to solve some very
strange bugs involving EOF, and I'd be worried that non-standard things
will make things worse.
Hope this helps. It's a somewhat confusing topic, but once you understand
it, you'll have a knowledge of what EOF is doing that is very valuable
when working with EOF.
You may also be interested to see some other comments on similar issues at:
http://wodev.spearway.com/cgi-bin/WebObjects/WODev.woa/wa/Main?wikiPage=GettingFreshDataFromDatabase
--Jonathan
>
> Thanks.
>
> Jean Pierre.
> _______________________________________________
> webobjects-dev mailing list | email@hidden
> Help/Unsubscribe/Archives:
> http://www.lists.apple.com/mailman/listinfo/webobjects-dev
> Do not post admin requests to the list. They will be ignored.
_______________________________________________
webobjects-dev mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/webobjects-dev
Do not post admin requests to the list. They will be ignored.