Opening Saved Objects
Opening Saved Objects
To open an object (load an object instance from disk into memory), use the %OpenId() method, which is as follows:
classmethod %OpenId(id As %String,
concurrency As %Integer = -1,
ByRef sc As %Status = $$$OK) as %ObjectHandle
Where:
-
id is the ID of the object to open.
In these examples, the ID is an integer. See The Object ID for information on other options
-
concurrency is the concurrency level (locking) used to open the object.
-
sc, which is passed by reference, is a %StatusOpens in a new tab value that indicates whether the call succeeded or failed.
The method returns an OREF if it can open the given object. It returns a null value ("") if it cannot find or otherwise open the object.
For example:
// Open person "10"
Set person = ##class(Sample.Person).%OpenId(10)
Write "Person: ",person,! // should be an object reference
// Open person "-10"
Set person = ##class(Sample.Person).%OpenId(-10)
Write "Person: ",person,! // should be a null string
You can also use the %Open() method, which requires an OID rather than an ID. An OID is a permanent identifier unique to the database that includes both the ID and the class name of the object. For more details, see Identifiers for Saved Objects: ID and OID.
To perform additional processing that executes when an object opens, you can define the %OnOpen() and %OnOpenFinally() callback methods. For more details, see Defining Callback Methods.
Multiple Calls to %OpenId()
If %OpenId() is called multiple times within an InterSystems IRIS process for the same ID and the same object, only one object instance is created in memory. All subsequent calls to %OpenId() return a reference to the object already loaded into memory.
For example, consider this class featuring multiple %OpenId() calls to the same object:
Class User.TestOpenId Extends %RegisteredObject
{
ClassMethod Main()
{
set A = ##class(Sample.Person).%OpenId(1)
write "A: ", A.Name
set A.Name = "David"
write !, "A after set: ", A.Name
set B = ##class(Sample.Person).%OpenId(1)
write !, "B: ", B.Name
do ..Sub()
job ..JobSub()
hang 1
write !, "D in JobSub: ", ^JobSubD
kill ^JobSubD
kill A, B
set E = ##class(Sample.Person).%OpenId(1)
write !, "E:", E.Name
}
ClassMethod Sub()
{
set C = ##class(Sample.Person).%OpenId(1)
write !, "C in Sub: ", C.Name
}
ClassMethod JobSub()
{
set D = ##class(Sample.Person).%OpenId(1)
set ^JobSubD = D.Name
}
}
Calling the Main() method produces these results:
-
The initial %OpenId() call loads the instance object into memory. The A variable references this object and you can modify the loaded object through this variable.
set A = ##class(Sample.Person).%OpenId(1) write "A: ", A.NameA: Uhles,Norbert F.
set A.Name = "David" write !, "A after set: ", A.NameA after set: David
-
The second %OpenId() call does not reload the object from the database and does not overwrite the changes made using variable A. Instead, variable B references the same object as variable A.
set B = ##class(Sample.Person).%OpenId(1) write !, "B: ", B.NameB: David
-
The third %OpenId() call, in the Sub() method, also references the previously loaded object. This method is part of the same InterSystems IRIS process as the Main() method. Variable C references the same object as variables A and B, even though those variables are not available within the scope of this method. At the end of the Sub() method, the process returns back to the Main() method, the variable C is destroyed, and variables A and B are back in scope.
do ..Sub()ClassMethod Sub() { set C = ##class(Sample.Person).%OpenId(1) write !, "C in Sub: ", C.Name }C in Sub: David
-
The fourth %OpenId() call, in the JobSub() method, is run in a separate InterSystems IRIS process by using the JOB command. This new process loads a new instance object into memory, and variable D references this new object.
job ..JobSub() hang 1 write !, "D in JobSub: ", ^JobSubD kill ^JobSubDClassMethod JobSub() { set D = ##class(Sample.Person).%OpenId(1) set ^JobSubD = D.Name }D in JobSub: Uhles,Norbert F.
-
The fifth %OpenId() call occurs after deleting all variables (A and B) that reference the loaded object in the original process, thereby removing that object from memory. As with the previous %OpenId() call, this call also loads a new instance object into memory, and variable E references this object.
kill A, B set E = ##class(Sample.Person).%OpenId(1) write !, "E:", E.NameE: Uhles,Norbert F.
To force a reload of an object being loaded multiple times, you can use the %Reload() method. Reloading the object reverts any changes made to the object that were not saved. Any previously assigned variables reference the reloaded version. For example:
set A = ##class(Sample.Person).%OpenId(1)
write "A: ", A.Name // A: Uhles,Norbert F.
set A.Name = "David"
write !, "A after set: ", A.Name // David
set B = ##class(Sample.Person).%OpenId(1)
write !, "B before reload: ", B.Name // David
do B.%Reload()
write !, "B after reload: ", B.Name // Uhles,Norbert F.
write !, "A after reload: ", A.Name // Uhles,Norbert F.
Concurrency
The %OpenId() method takes an optional concurrency argument as input. This argument specifies the concurrency level (type of locks) that should be used to open the object instance.
If the %OpenId() method is unable to acquire a lock on an object, it fails.
To raise or lower the current concurrency setting for an object, reopen it with %OpenId() and specify a different concurrency level. For example,
set person = ##class(Sample.Person).%OpenId(6,0)
opens person with a concurrency of 0 and the following effectively upgrades the concurrency to 4:
set person = ##class(Sample.Person).%OpenId(6,4)
Specifying a concurrency level of 3 (shared, retained lock) or 4 (shared, exclusive lock) forces a reload of the object when opening it. For more information on the possible object concurrency levels, see Specifying Concurrency Options.