Re: [Modeling-users] slooow delete
Status: Abandoned
Brought to you by:
sbigaret
From: Sebastien B. <sbi...@us...> - 2005-03-11 21:19:48
|
John Lenton <jl...@gm...> wrote: > On 10 Mar 2005 15:10:59 +0100, Sebastien Bigaret > <sbi...@us...> wrote: > >=20 > > I'd like to understand why so many objects are fetched (is there, by any > > chance, a to-many relationships without an inverse relationship defined > > pointing back to the object?) >=20 > I'm pretty certain there isn't; this is the entity I'm deleting (sans > the non-relationship properties): Just to be clear: I did not meant that having such a relationship (without an inverse defined) is a bad thing, I was just thinking loudly about the reason why so much objects were fetched... but I did not think about the (now) obvious reasons: >=20 > Entity ('Task', > properties=3D [ > RToOne ('need', 'Need', joinSemantic=3D2, inverse=3D'task= s'), > RToOne ('team', 'Team', joinSemantic=3D2, inverse=3D'task= s'), > RToOne ('mealType', 'MealType', joinSemantic=3D2, > inverse=3D'tasks'), > ], > ), >=20 > the weird thing is that the entities it loads are all Tasks, the same > thing (a whole load of Tasks getting loaded) happens upon insert; what > triggers it in that case is >=20 > team.addToTasks(task) >=20 > whereas on the previous line I have a >=20 > need.addToTasks(task) >=20 > and that doesn't trigger it. Okay: when addToTasks() is called: 1. the to-many fault is triggered, fetching all related objects and populating the corresponding list, here 'self._tasks' probably, 2. the new task is added to the list. The fact that need.addToTasks(task) does not trigger any fetch simply means that the to-many faults is already cleared --or that it also triggers the fetch but you do not notice it since that 'need' object does not have (many) tasks assigned. Back to your problem in ec.delete(task): when ec.processRecentChanges() is called, it examines your object's relationships: 'need', 'team' and 'mealType', all three being of type DELETE_NULLIFY. So: at processRecentChanges() time the ec takes care of the deletion policy. For that purpose, in this case it gets these 3 related objects: need, team and mealType (using KeyValueCoding) and removes the deleted object 'task' from their tasks... but when it does that, *it triggers all three to-many faults*: need.tasks, team.tasks and mealType.tasks... and I suspect that at least one of them is quite big. Now we know why we have 1 deleted object, 3 updated ones (the related need, team and mealType), and a bunch of fetched Tasks in the ec after processRecentChanges(). And your next question will probably be: okay, and how to change that behaviour? Here is a description of what should be a definitive solution, and then a workaround you may use till that solution is implemented. Changing the default baheviour requires that ec.processRecentChanges() becomes smarter: it should be changed so that it detects that the related objects 'need', 'team' and 'mealType' do not need to be fetched if they are not cached yet, or that their to-many faults 'tasks' should not be cleared if they hasn't been yet (including: in an other EC), because simply deleting the object removes the only information where both the relationship and its inverse is stored: the Foreign Key stored in the deleted object tasks's DB-row pointing to resp. tables NEED, TEAM and MEAL_TYPE. [1] I probably won't have the time for this in the coming weeks; I'm currently overwhelmed by work and (luckily!) personal activities. In the mean time you can bypass that behaviour by removing the related objects: task.setNeed(None) task.setTeam(None) task.setMealType(None) ec.delete(task) ec.saveChanges() Note: if, for example, the related 'team' object is the only one that has a big bunch of 'Tasks in stored in its inverse relationship, you can simply setTeam(None) and leave the other objects be fetched and updated by the default behaviour. I'm saying this because there is a=20 *Big fat warning* (!): do that if you're absolutely sure that the related 'need', 'team' and 'mealType' objects are not already fetched in other ECs, *or*, if they are fetched, that the "inverse" tomany faults are not cleared. Respectively, check that (for 'need', same for 'team' and 'mealType'): db=3Dec.rootObjectStore().objectStoreForObject(task).database() task_need_gID=3Dtask.getNeed().globalID() db.snapshotForGlobalID(task_need_gID=3Dtask) # None if unfetched yet and if it's not None: db.snapshotForSourceGlobalID(task_need_gID, 'tasks') # should be () Otherwise you may experience weird side-effects on the corresponding objects already fetched in other ECs, esp. when saving them (no pb. if you use a single EC in the app., however). Hopefully this will help. -- S=E9bastien. [1] some further notes about the internals you can safely ignore (I'll use this post when working on the problem later): to be precise, propagateDeleteForObject() should be changed here. And the Database's cache should also be changed accordingly, esp. in case where the related objects are already fetched and the corresponding to-many faults are already cleared. Plus, when notification of changes is implemented, notification of changes for related objects should be posted as well (even if the objects are not actually fetched nor their tomany faults cleared for efficiency reasons)--this implies that EntityClassDescription's method propagateDeleteForObject() has a mean to communicate that information back to the EC for use at the end of the saveChanges() process when notifications are broadcasted) >=20 > Here are the Relationships defined in both Need and Team: >=20 > Entity ('Team', > properties=3D [ > RToOne ('offer', 'Offer', joinSemantic=3D2, inverse=3D'te= ams'), > RToMany ('tasks', 'Task', inverse=3D'team'), > RToMany ('userTeams', 'UserTeam', inverse=3D'team'), > ], > ), > Entity ('Need', > properties=3D [ > RToOne ('category', 'Category', joinSemantic=3D2, > inverse=3D'needs'), > RToOne ('sponsor', 'User', joinSemantic=3D2, inverse=3D'n= eeders'), > RToOne ('offer', 'Offer', joinSemantic=3D2, inverse=3D'ne= eds'), > RToOne ('user', 'User', joinSemantic=3D2, inverse=3D'need= s'), > RToOne ('visibility', 'Visibility', joinSemantic=3D2, > inverse=3D'needs'), > RToMany ('tasks', 'Task', inverse=3D'need'), > ], > ), >=20 >=20 > --=20 > John Lenton (jl...@gm...) -- Random fortune: > Don't anthropomorphise computers and cars, They hate that. |