%OnAddToSaveSet - what has changed

Primary tabs


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


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)  

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 user
ClassMethod 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()

  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 state
Method ModificationState()
  write "Object modified: ", $system.CLS.GetModified(), !
  write "Name prop modified: ", ..IsNameModified(), !, !

/// Get name property modification status
Method 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.

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%PropName and m%PropName,
but these are not supported for direct use.

And no hint how they could be used.

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

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()

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.

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