Esteban, Alan,
thanks a lot for your comments. So my expectation wasn't wrong, that is good to know.
So I tried digging down a little deeper. GlorpSession>>refresh: does indeed privateRegisterAsOld: the newly read / updated object. I think the problem is in ObjectTransaction>>#register:.
Please take a look at this screenshot of my VAST Debugger:
As you can see, refresh: tries to register teh newly read Customer who is now named 'Harry Flutter', which is what was read from the DB.
So we have a realObject which is the correctly named one we are refreshing, and we have the old one ('Albert Hughes') as value in the undoMap:
Now register decides: to not update the value in the undoMap because teh realObject ('Harry Flutter') is already registerd as key. But it is associated with the outdated copy named 'Albert Hughes'.
So I wonder if just removing the includesKey: check would be the right solution. I understand it is more or less just a performance optimization (but maybe a big one, in case of Collections).
Or would it be better to add a check for equality on the value of the undoMap entry? Something along the lines of:
register: anObject
"Make anObject be a member of the current transaction. Return the object if registered, nil otherwise"
| copy realObject |
realObject := self realObjectFor: anObject ifNone: [^nil].
"The next line inlines #isRegistered: - we just got the real object so need not get it again."
"Suggested change by Joachim Tuchel to make sure #refresh:ed objects get updated properly "
(undoMap at: realObject ifAbsent: []) ifNotNil: [:regObj| regObj = realObject ifTrue: [^nil]].
copy := self shallowCopyOf: realObject ifNotNeeded: [^nil].
undoMap at: realObject put: copy.
self registerTransientInternalsOfCollection: realObject.
^realObject
I checked my test case and this change yields the expected outcome. I thought that is it.
BUT: it breaks the Glorp Tests: I get a StackOverflows in GlorpManyToManyDBTest>>#testReadAndDeleteNodes in UnitOfWork>>register: when it tries to registerTransitiveClosureFRom: of an Array . So my change to ObjectTransaction>>#register: doesn't break, it "only" causes side effects ;-)
So I tried all kinds of extra guards for proxies or collections for realObject. I also tried using includesKey: first and only ifTrue would I access undoMap at: realObject. But still I get StackOverflows.
In short; I am lost for now and need help getting this to work.
Any comments?
Joachim