Question
Alex Kogan · Mar 5

After saving swizzled objects, is it possible to open a direct ref and verify saved data without closing the original parent.

I have a quick question regarding swizzled objects.

I have an original object, say Object a, I am working with.

I set a property a.something.somethingother.somethingelse.myNewProperty  to some value x.

Then at some point I am saving a and continuing to work with it.  I assume here by saving a, I saved myNewProperty as well. (as it should work)

At some point  I would like to make certain that I have correct value in my myNewProperty, so since I happen to know it's ID I 
open it directly:
Set ref=##class(somethingelse).%OpenId(Id)
but when I try to look at my ref.myNewProperty it seem to be displaying the value of a.something.somethingother.somethingelse.myNewProperty 
and not value of ref.myNewProperty.    

I am not certain if there is an answer, but would like to know if it is possible or that it is not possible without closing my parent ref a.

Thank you

Product version: IRIS 2020.1
20
2 0 5 106
Log in or sign up to continue

If I understand what you're asking correctly, this is a really great question that hits on a kind of tricky aspect of ObjectScript/persistence. In short, if you already have a persistent object in memory (with a variable, say thingOne, assigned to it), and you open the same ID again and assign another variable to it (say, thingTwo), the OREF will be reused - both variables will point to the same object, and that one in-memory instance of the object can be modified via either variable. This can easily lead to some confusing scenarios.

Here's a quick demonstration of the fact:

Class DC.Demo.OREFOIDDemo Extends %Persistent
{

Property Foo As %String;

ClassMethod RunDemo()
{
    Do ..%KillExtent()
    
    Set thingOne = ..%New()
    Set thingOne.Foo = "Bar"
    Do thingOne.%Save()
    
    Set thingTwo = ..%OpenId(thingOne.%Id())
    Set thingTwo.Foo = "Baz"
    
    Write !,"thingOne = ",thingOne
    Write !,"thingTwo = ",thingTwo
    Write !,"thingOne.Foo = ",thingOne.Foo
    Write !,"thingTwo.Foo = ",thingTwo.Foo
}

}

Running the method produces the output:

Do ##class(DC.Demo.OREFOIDDemo).RunDemo()

thingOne = 18@DC.Demo.OREFOIDDemo
thingTwo = 18@DC.Demo.OREFOIDDemo
thingOne.Foo = Baz
thingTwo.Foo = Baz

It may surprise you that thingOne.Foo has also been set to "Baz" - but as you can see, thingOne and thingTwo reference the same object.

Note that if for some reason I wanted to know the current persisted value of thingOne.Foo, I could use:

thingOne.FooGetStored(thingOne.%Id())

If what you're describing is actually that a deep save isn't working, this might just be something else entirely. :)

In communication outside of this thread, turns out the issue stemmed from a failed %Save() - something like:

Class DC.Demo.OREFOIDDemo Extends %Persistent
{

Property Foo As %String(VALUELIST = ",Bar");

ClassMethod RunDemo()
{
    Do ..%KillExtent()
    
    Set thingOne = ..%New()
    Set thingOne.Foo = "Bar"
    Do thingOne.%Save()
    Set thingOne.Foo = "Baz"
    Do thingOne.%Save()
    
    // Later, and elsewhere, because thingOne happens to be in memory,
    // it appears that the value "Baz" has been persisted:
    
    Set thingTwo = ..%OpenId(thingOne.%Id())
    
    Write !,"thingOne = ",thingOne
    Write !,"thingTwo = ",thingTwo
    Write !,"thingOne.Foo = ",thingOne.Foo
    Write !,"thingTwo.Foo = ",thingTwo.Foo
    
    Write !,"thingOne.FooGetStored(thingOne.%Id()) = ",thingOne.FooGetStored(thingOne.%Id())
    
    Do thingTwo.%Reload()
    Write !,"After thingTwo.%Reload(), thingOne.Foo = ",thingOne.Foo
    Write !,"After thingTwo.%Reload(), thingTwo.Foo = ",thingOne.Foo
}

}

Which produces output:

Do ##class(DC.Demo.OREFOIDDemo).RunDemo()
thingOne = 15@DC.Demo.OREFOIDDemo
thingTwo = 15@DC.Demo.OREFOIDDemo
thingOne.Foo = Baz
thingTwo.Foo = Baz
thingOne.FooGetStored(thingOne.%Id()) = Bar
After thingTwo.%Reload(), thingOne.Foo = Bar
After thingTwo.%Reload(), thingTwo.Foo = Bar

I like the GetStored answer, which would work perfect in my case to make certain the child is stored properly.  

In my real life example, the original save used %Save(0) and therefore did not save somethingelse.myNewProperty, but it was still displaying the correct value when I was (ref it directly) and writing it out, as it was getting it from memory.