Written by

Question Jiri Svoboda · May 21, 2018

%OnAddToSaveSet - what has changed

Hi community,

what is the best way to determine if a certain property got changed between %OpenId and %Save? Preferably in the %OnAddToSaveSet method.

Thanks,

Jiri

Comments

Robert Cemper · May 21, 2018

If you look for a dedicated Property You may use  <propertyname>GetStored(id) to compare against the object in memory

e.g.

set id=22
set old=##class(Sample.Person).SSNGetStored(id)

so you bypass also the case when a value is written back finally unchanged  (false modified)  

0
Robert Cemper  May 21, 2018 to Eduard Lebedyuk

I know of i%PropName

where is  m%PropName documented?

all I found is:

Internally, Caché also uses additional instance variables with names such as r%PropNameand m%PropName,
but these are not supported for direct use.

And no hint how they could be used.

0
Eduard Lebedyuk · May 21, 2018

You can determine that in run time with:

  • $system.CLS.GetModified(oref) to ger if oref was modified
  • m%property to get if property changed

Here's a simple example of how it all works

Class User.Person Extends (%Persistent){Property Name As %String(DISPLAYNAME = "Name");Property Age As %Integer(DISPLAYNAME = "Age");/// Create one userClassMethod Recreate() As %Status{  do ..%KillExtent()  set person = ..%New()  set person.Age = $random(100)  set person.Name = $random(100)   quit person.%Save()}/// do ##class(User.Person).Test()ClassMethod Test(){  $$$QuitOnError(..Recreate())  set person = ..%OpenId(1)  do person.ModificationState()  set person.Age = $random(100)  do person.ModificationState()  set person.Name = $random(100)  do person.ModificationState()}/// Show current object stateMethod ModificationState(){  write "Object modified: ", $system.CLS.GetModified(), !  write "Name prop modified: ", ..IsNameModified(), !, !}/// Get name property modification statusMethod IsNameModified() As %Boolean{  quit m%Name}}

Executing in terminal:

>do ##class(User.Person).Test()
Object modified: 0
Name prop modified: 0
 
Object modified: 1
Name prop modified: 0
 
Object modified: 1
Name prop modified: 1

Note that changing value back would still mark property as modified.

0
Eduard Lebedyuk  May 21, 2018 to Robert Cemper

m%PropName returns 1 if the property value was modified, 0 if not.

0
Robert Cemper  May 21, 2018 to Eduard Lebedyuk

do you have any indication if this is just isModified() 

or if new content is checked against old content

Reason: in past isModified () just checked write access, not the content.
So a change from TRUE to FALSE and back to TRUE between %OpenId()  and %Save() was marked as change (false positive)

so this was finally dropped in favor of GetStored()
 

0
Eduard Lebedyuk  May 21, 2018 to Robert Cemper

As I originally said

Note that changing value back would still mark property as modified.

Any change (except immediate same value) would set m%PropName to 1.

I think that checking m%PropName and only if it equals one additionally checking GetStored would work faster.

0
Robert Cemper  May 21, 2018 to Eduard Lebedyuk

An interesting combination!

But (from Sample.Person):

zNameGetStored(id) public {
Quit $Select(id'="":$listget($g(^Sample.PersonD(id)),2),1:"") }


there isn't that much to win.
If it then ends with %Save() it is kind of a prefetch of the global buffer.

I saw it mostly used instead of  %Open() loading / swizzling the whole object in memory
if just 1 specific property was required.
(A kind of direct global access in disguise) smiley

0