Un-Typical persistence

Primary tabs

During my search for a snapshot of a persistent object,
I met a feature that I would like tho share as it could be useful in some special situations.
My trigger was to have a before- and an after-image during unit testing. A typical persistent class may have a storge definition like this

Storage Default
{
 <Data name="kDefaultData">
 +<Value name="1">
 </Value>
 </Data>
 <DataLocation>^otto.kD</DataLocation>
 <DefaultData>kDefaultData</DefaultData>
 <IdLocation>^otto.kD</IdLocation>
 <IndexLocation>^otto.kI</IndexLocation>
 <StreamLocation>^otto.kS</StreamLocation>
 <Type>%Storage.Persistent</Type>
}

Now I applied this change: 

  Parameter MANAGEDEXTENT = 0; ;extent manager dislikes this change

Storage Default
{
 <Data name="kDefaultData">
 +<Value name="1">
  </Value>
 </Data>
 <DataLocation>@(%storage_"D")</DataLocation>
 <DefaultData>kDefaultData</DefaultData>
 <IdLocation>@(%storage_"D")</IdLocation>
 <IndexLocation>@(%storage_"I")</IndexLocation>
 <StreamLocation>@(%storage_"S")</StreamLocation>
 <Type>%Storage.Persistent</Type>
}

All you have to do now to use it:

set %storage="^myGlobal"         ;; normal use with ROLLBACK
or 
set %storage="%myLocalVariable"  ;; no ROLLBACK
or
set %storage="^||myPPG"          ;; no ROLLBACK

and it works as you are used to it.
Except for ROLLBACK as there is, of course,  no Journal behind PPG or local variables 

A typical use sequence to prepare a check for changes could look similar:

set %storage="^otto.k" 
set obj=##class(otto.k).%OpenId(id)       ;; get original
do obj.%SetModified(1)                    ;; prepare for %Save
set %storage="^||otto"                    ;; location of copy
set sc=obj.%Save()                        ;; write copy to temp storage
//// carry on with testing and changes and find what happened

 

 I think it's worth to share it.

Comments

This is nifty! Note, you can make the extent manager happy by using:


Class DC.Demo.SometimesPersistent Extends %Persistent
{

Property Foo As %String;

ClassMethod Demo()
{
    New %storage,%fooD,%fooI,%fooS
    Set obj = ##class(DC.Demo.SometimesPersistent).%New()
    Set obj.Foo = "bar"
    Set %storage = "%foo"
    Write !,obj.%Save()
    Kill obj
    Set obj = ..%OpenId(1)
    w ! zw obj
    zw %fooD
}

Storage Default
{
<Data name="SometimesPersistentDefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
<Value name="2">
<Value>Foo</Value>
</Value>
</Data>
<DataLocation>@($Get(%storage,"^DC.Demo.SometimesPersistent")_"D")</DataLocation>
<DefaultData>SometimesPersistentDefaultData</DefaultData>
<IdLocation>@($Get(%storage,"^DC.Demo.SometimesPersistent")_"D")</IdLocation>
<IndexLocation>@($Get(%storage,"^DC.Demo.SometimesPersistent")_"I")</IndexLocation>
<StreamLocation>@($Get(%storage,"^DC.Demo.SometimesPersistent")_"S")</StreamLocation>
<Type>%Library.CacheStorage</Type>
}

}

ATTENTION:   
- This fails if your class has as UNIQUE index
- There can be issues with new inserted objects