More: Deleted Object Becoming Updated Object During processRecentChanges
Chuck Hill <[email protected]>
| Newsgroups | gmane.comp.web.webobjects.eof |
|---|---|
| Organization | Global Village Consulting, Inc. |
| Message-ID | <[email protected]> |
I've found a bit more about what is going on and have managed to fix my particular situation. As near as I can figure out, this is what is happening: - object is deleted: ec.deleteObject(tableToDelete) - processRecentChanges() is invoked - while propagating the deletion, a fault is fired for the related object - the snapshot for the EO is in the object store, but older than what the editing context will accept because of (EOEditingContext.setDefaultFetchTimestampLag(2000)) - the row is fetched from the database - the fetched row does not match the existing snapshot - the ObjectsChangedInStoreNotification notification is broadcast for the refreshed object(s) - the editing context receives this message and does something (resets?) that causes the lists of updated, inserted, and delete objects to be lost - control is returned to processRecentChanges - all hell breaks loose :-) In my case this was caused by a Timestamp attribute. NSTimestamp is accurate to the millisecond, while java.sql.Timestamp is only accurate to the second. Whenever a newly inserted row containing a timestamp is refetched the snapshots won't match and this notification will be broadcast (I think, I've not confirmed this too carefully yet). In most cases this will not matter, and in fact will not happen if you are using the defaultFetchTimestampLag and not refreshing refetched objects. It only seems to have a bad effect when it happens while processRecentChanges is in progress. My solution to this particular problem was simply to create an NSTimestmap with milliseconds of zero: GregorianCalendar gc = new GregorianCalendar(); gc.setTime(new NSTimestamp); gc.set(GregorianCalendar.MILLISECOND, 0); NSTimestamp timeToSecond = new NSTimestamp(gc.getTime()); However, the same thing will happen if another process has updated the database. I think I might be missing one piece to this puzzle, as I expect it to also happen in another piece of code and it does not. I'll work on it more later and see if I can get a rock solid reproduction case to send to Apple. If anyone has any insights into this they would be most appreciated. Chuck Chuck Hill wrote: > Hi, > > I'm coming close to losing my mind over this one... > > I've got two EOs, Table and Column. Table has many Columns, each Column > has one > Table. Table cascade deletes Columns. A Column nullifies it's Table's > reference upon deletion. I'm working with a third EO that is a > sub-class of a > sub-class of Table. > > Here is the code: > > EOEditingContext ec = new EOEditingContext(); > ec.lock(); > // selectedDatabaseTable() is a sub-class of a sub-class of Table > Table tableToDelete = (Table) EOUtilities.localInstanceOfObject(ec, > selectedDatabaseTable()); > ec.deleteObject(tableToDelete); > // This next line was added for debugging > ec.processRecentChanges(); > ec.saveChanges(); > ec.unlock(); > > > The symptom I am seeing is that validateForSave is getting called on > tableToDelete after the delete rules have been applied. However, this only > happens in one specific situation: deleting a new table that has just been > created an saved in session().defaultEditingContext(). If the table is > created > and then the user logs out and in, then deletion proceeds normally. The > deletion proceeds normally if the application is stopped and restarted. > The deletion proceeds normally if another user logs in and deletes it > while the creating session is still active. > > I notice that if I print out ec.updatedObjects() and ec.deletedObjects() > before > and after ec.processRecentChanges(), that tableToDelete has been removed > from > deletedObjects() and added to updatedObjects() when > processRecentChanges() returns. This would explain why > validateForSave() is being called on it. > > After much debugging and hair pulling I've determined (or think that I have > determined) that this is caused by processRecentChanges() firing a fault > for a > Column object that triggers a trip to the database. This seems to be > happening > at the wrong time when the table was recently created. I can avoid the > error I > am getting by iterating over tableToDelete.columns() and manually firing > the > faults by printing out an attribute. > > Possibly somewhat related is my use of > EOEditingContext.setDefaultFetchTimestampLag(2000); > If I set this up from two seconds to twenty seconds, and delete the > table within > 20 seconds of creating it, then I see no error. However, if I wait > longer than > 20 seconds the result is the same as having this at two seconds. > > > Does anyone have any ideas on why this might be happening only after the > EO is > created? > > > Chuck > > -- Chuck Hill [email protected] Global Village Consulting Inc. http://www.global-village.net Don't think mink, think weasel!