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.
|