Re: Modeling an optional to-one relationship
Re: Modeling an optional to-one relationship
- Subject: Re: Modeling an optional to-one relationship
- From: Chuck Hill <email@hidden>
- Date: Fri, 15 Jan 2010 10:52:59 -0800
Hi Mark,
On Jan 15, 2010, at 12:08 AM, Mark Ritchie wrote:
Hi Chuck!
On 14/Jan/2010, at 1:46 PM, Chuck Hill wrote:
On Jan 14, 2010, at 3:36 AM, Mark Ritchie wrote:
Yes, I believe that's the intended behaviour... The
DatabaseContext tracks that newly created EO and throws an
exception if you attempt to modify and then save it.
Almost, it throws when the fault is fired.
Hrm, in test case that I constructed, that's not what I observe.
I'm using WOF 5.4.3, Java 1.5 on my development machine.
I wonder if we are mis-communicating. What are you describing below
seems to be the default behavior if NOT using the delegate method from
Kelly Hawk. Is this below result from the code you posted later
(Application.java)?
Using the Movies EOModel and local mysql:
I fetch a Talent EO.
I ask for it's photo and get back a fault for the TalentPhoto EO (as
expected.)
Kelly's delegate method should throw here (or maybe in the step before).
Chuck
I fire the fault and get back a TalentPhoto EO with PK set and nil
values.
EODatabaseContext.objectsWithMissingGlobalIds() confirms that it's
tracking the TalentPhoto EO for me.
I make a change to the Talent EO and save it.
All is good.
I make changes to TalentPhoto:set a photo and set it's talent
relationship to the Talent EO.
Then when I try to save changes, EOF tosses a
EOObjectNotAvailableException with this explanation:
prepareForSaveWithCoordinator: Cannot save the object with globalID
_EOIntegralKeyGlobalID[TalentPhoto (java.lang.Integer)1]. The row
referenced by this globalID was missing from the database at the
time a fetch was attempted. Either it was removed from the database
after this application got a pointer to it, or there is a
referential integrity problem with your database. To be notified
when fetches fail, implement a delegate on EODatabaseContext that
responds to databaseContextFailedToFetchObject().
That explanation seems to match what I've done and the behaviour
seems to match the documentation for EODatabaseContext's delegate
databaseContextFailedToFetchObject(). http://tr.im/dcdelegate
What am I doing differently then you?
No DB Context delegate is my guess. :-) You may also find this code
useful or interesting.
/**
* Detecting WO 5 dummy fault EOs. The code below is a
translation of code posted here:
* From http://wodeveloper.com/omniLists/eof/2001/November/msg00023.html
*
* As of WO4.5, EOF resolves faults for objects that don't exist
in the database to a dummy object with mostly empty attributes (except
those
that are set in -init), whereas earlier versions of EOF threw a
_fireFault exception. This method detects whether the receiver is
such a dummy object.
*
* A distinguishing feature of these dummy EOs is that they
don't have a corresponding database context snapshot, so we use this
to detect its dummy-ness. This seems more robust than checking if all
or most attributes are empty, since these can be changed by client code.
*
* Dummy fault EOs should be removed from the editingContext
(using forgetObject) before it is invalidated (invalidateAllObjects or
invalidateObjectWithGlobalID), otherwise an unrecoverable
"decrementSnapshotCountForGlobalID - unable to decrement snapshot
count for object with global ID" exception is thrown by EOF.<br><br>
*
* See also: http://www.omnigroup.com/mailman/archive/eof/2001-May/001988.html
andfollowing.
*/
public static boolean isDummyFaultEO(EOEnterpriseObject anObject)
{
/** require [valid_param] anObject != null; **/
JassAdditions.pre("EOObject", "isDummyFaultEO
[object_in_ec]", anObject.editingContext() != null);
JassAdditions.pre("EOObject", "isDummyFaultEO
[object_has_global_id]",
anObject.editingContext().globalIDForObject(anObject) != null);
boolean isDummyFaultEO = false;
// This method will fail if the object is still a fault. We
fire the fault so that the correct result is returned.
if (anObject.isFault())
{
try
{
anObject.willRead();
}
catch (EOObjectNotAvailableException e)
{
// The DatabaseContextDeletgate restores the "throw
on failure to fetch" functionality and throws
EOObjectNotAvailableException
// That is caught here and true returned so that this
method will return the expected result even when this delegate is used
return true;
}
}
EOEditingContext ec = anObject.editingContext();
EOGlobalID globalID = ec.globalIDForObject(anObject);
// NB. objects with temporary globalIDs legitimately have no
DB snapshots, since these are by definition not yet saved to the
database.
if (! globalID.isTemporary())
{
// Find the EODatabaseContext instance associated with
anObject, or null if no databaseContext association can be found.
EOObjectStoreCoordinator rootStore =
(EOObjectStoreCoordinator)ec.rootObjectStore();
rootStore.lock();
try
{
EODatabaseContext dbContext =
(EODatabaseContext)rootStore.objectStoreForObject(anObject);
if (dbContext == null)
{
throw new RuntimeException("Could not locate
EODatabaseContext for object '" +
anObject + "' in
editingContext: " + ec);
}
isDummyFaultEO =
(dbContext.snapshotForGlobalID(globalID) == null);
}
finally
{
rootStore.unlock();
}
}
return isDummyFaultEO;
}
--
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
_______________________________________________
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