Hi Alan,
hmm. What you say makes sense. Remove the object frm collections in my Smalltalk code by hand and then have the Glorp session delete the object.
This will, however not work in some situations. Mine is such a situation. Let me explain ( I was hoping I can keep this whole thing simple, but I can't):
Take an object model of a typical Bill-of-materials kind:
Part --- 1:n, beExclusive --> CompositeSubpart -- 1:n, beExclusive --> Subpart
Say I want to delete one of the CompositeSubparts from a Part and want Glorp to handle the deletion of all Subparts in that CompositeSubpart.Something like this:
myCar subparts remove: dashboard.
self session delete: dashboard.
self session commitUnitOfWorkAndContinue.
This will issue delete statements for the dashboard and all its subparts. Good.
BUT: When is the right point in time to remove the subparts from the dashboard's (CompositeSubpart) collection of subparts?
If I remove them before the commit, Glorp will not delete them, because at the very moment Glorp tries to find out which objects to delete, there is no entry for the subparts in the dashboard's subparts collection. Am I right?
If I remove them after the Commit, Glorp will re-register them, because the dashboard's subparts collection will still include the supparts.
So I see no way around Glorp removing all deleted objects from all collections that get re-registered in commitUnitOfWorkAndContinue and thereby changing the state of model objects. There is a naive approach to it: not only remove the deleted objects from the registeredObjects collection, but also form all collections inside registeredObjects. The cleaner approach would surely be to walk through the descriptor system. It would be slower and th outcome would probably not be any better.
So I suggest something along the lines of:
commitUnitOfWorkAndContinue
"Commit the current unit of work, but then keep going with the same set of registered objects, with their state updated to reflect current values."
| registeredObjects |
currentUnitOfWork isNil ifTrue: [^self error: 'Not in unit of work'].
registeredObjects := currentUnitOfWork registeredObjects.
currentUnitOfWork deletedObjects do: [:each |
registeredObjects remove: each.
registeredObjects do: [:rO| (rO isKindOf: Collection) ifTrue: [rO remove: each] ]].
self commitUnitOfWork.
self beginUnitOfWork.
self registerAll: registeredObjects.
But is that enough? Will it change the original collections in the business objects (meaning: are the registeredObjects the objects I am using in my business code?)?
What do you think about this? Am I wrong with my dashboard->subparts hypothesis?
Joachim
BTW: in the meantime, I found out that commitUOW + beginUOW will not really solve my problem, because it introduces exactly the problem which commitUnitOfWorkAndContinue aims to solve: objects that were registered before the commit will not be registered afterwards, so consecutive commits will not see any changes to objects that were read in the same session but before the first commit. I'd have to reregister (or maybe refresh?) all objects that I want to change in consectutive commits in the same session. That is not a nice approach...