Replies:

Caché 5.0.21:

Class DC.DemoPropertyQuery Extends %Persistent ClassType = persistent, ProcedureBlock ]
{

Property Foo As %String;

Property Bar As %Boolean;

ClassMethod Benchmark()
{
  set Job=##CLASS(%SYSTEM.Process).%OpenId($job)
  
  set start $zhorolog
  set startGlobalRefs Job.GlobalReferences
  set startLines Job.LinesExecuted
  for i=1:1:1000 {
    kill properties
    do ..GetPropertiesAsQuickly(.properties)
  }
  set endLines Job.LinesExecuted
  set endGlobalRefs Job.GlobalReferences
  write "Elapsed time (1000x): ",($zhorolog-start)," seconds; ",(endGlobalRefs-startGlobalRefs)," global references; ",(endLines-startLines)," routine lines",!
  
  do ..Print(.properties)
  write !
}

ClassMethod Print(ByRef properties)
{
  set key ""
  for {
    set key $order(properties(key),1,data)
    quit:key=""
    set $listbuild(type,origin) = data
    write !,"property: ",key,"; type: ",type,"; origin: ",origin
  }
}

ClassMethod GetPropertiesAsQuickly(Output properties)
{
  // Getting properties via macro-wrapped direct global references is harder to read,
  // but is the fastest way to do it.
  set key ""
  set class = ..%ClassName(1)
  for {
    set key $$$comMemberNext(class,$$$cCLASSproperty,key)
    quit:key=""
    set type $$$comMemberKeyGet(class,$$$cCLASSproperty,key,$$$cPROPtype)
    set origin $$$comMemberKeyGet(class,$$$cCLASSproperty,key,$$$cPROPorigin)
    set properties(key) = $listbuild(type,origin)
  }
}

}

Result:

USER>do ##class(DC.DemoPropertyQuery).Benchmark()
Elapsed time (1000x): .018047 seconds; 25003 global references; 40000 routine lines
 
property: %Concurrency; type: %Library.CacheString; origin: %Library.Persistent
property: %IsInSave; type: %Library.CacheString; origin: %Library.Persistent
property: Bar; type: %Library.Boolean; origin: DC.DemoPropertyQuery
property: Foo; type: %Library.String; origin: DC.DemoPropertyQuery

See $SYSTEM.SQL.SetServerInitCode() (there are differences for IRIS)

Simple example:

Class dc.test
{

ClassMethod Test()
{
  
  programname=$zcvt(##class(%SYS.ProcessQuery).%OpenId($j).ClientExecutableName,"L")

  programname="blablabla.exe" {

    ;useful work

    s $EC="ERROR"
    ;or
    s $ROLES="r1"
  }
}

}

USER>d $SYSTEM.SQL.SetServerInitCode("d ##class(dc.test).Test()")

Now, when connecting from a specific program via ODBC/JDBC to namespace "USER", an error will occur. You can configure something another.

See Parent-Child Relationships and Storage

Demonstration:

  1. Class dc.child Extends %Persistent
    {
    Property name;
    Property parent As dc.parent;
    // Relationship parent As dc.parent [ Cardinality = parent, Inverse = child ];
    }
    
    Class dc.parent Extends %Persistent
    {
    Property name;
    // Relationship child As dc.child [ Cardinality = children, Inverse = parent ];
    ClassMethod Test()
    {
      ..%KillExtent()
      ##class(child).%KillExtent()
      
      &sql(insert into dc.parent(namevalues('parent1'))
      &sql(insert into dc.parent(namevalues('parent2'))
    
      &sql(insert into dc.child(name,parentvalues('child11',1))
      &sql(insert into dc.child(name,parentvalues('child12',1))
      &sql(insert into dc.child(name,parentvalues('child21',2))
      &sql(insert into dc.child(name,parentvalues('child22',2))
      
      zw ^dc.parentD,^dc.childD
    }
    }
    USER>##class(dc.parent).Test()
    ^dc.parentD=2
    ^dc.parentD(1)=$lb("","parent1")
    ^dc.parentD(2)=$lb("","parent2")
    ^dc.childD=4
    ^dc.childD(1)=$lb("","child11",1)
    ^dc.childD(2)=$lb("","child12",1)
    ^dc.childD(3)=$lb("","child21",2)
    ^dc.childD(4)=$lb("","child22",2)
  2. Important: do not touch the existing Storages in both classes!!!
    Class dc.child Extends %Persistent
    {
    Property name;
    //Property parent As dc.parent;
    Relationship parent As dc.parent Cardinality = parent, Inverse = child ];
    Storage Default
    {
    ...
    }
    }
    
    Class dc.parent Extends %Persistent
    {
    Property name;
    Relationship child As dc.child Cardinality = children, Inverse = parent ];
    ClassMethod Test()
    {
     ...
    }
    Storage Default
    {
    ...
    }
    }
    USER>##class(dc.parent).Test()
    ^dc.parentD=2
    ^dc.parentD(1)=$lb("","parent1")
    ^dc.parentD(2)=$lb("","parent2")
    ^dc.childD=4
    ^dc.childD(1,1)=$lb("","child11",1)
    ^dc.childD(1,2)=$lb("","child12",1)
    ^dc.childD(2,3)=$lb("","child21",2)
    ^dc.childD(2,4)=$lb("","child22",2)
  3. Important: now remove Storage from dc.child class and recompile both classes. Note that now the Storage of the dc.child class has changed.
    USER>##class(dc.parent).Test()
    ^dc.parentD=2
    ^dc.parentD(1)=$lb("","parent1")
    ^dc.parentD(1,"child",1)=$lb("","child11")
    ^dc.parentD(1,"child",2)=$lb("","child12")
    ^dc.parentD(2)=$lb("","parent2")
    ^dc.parentD(2,"child",3)=$lb("","child21")
    ^dc.parentD(2,"child",4)=$lb("","child22")
    ^dc.childD=4
    ^dc.childD(1,1)=$lb("","child11",1)
    ^dc.childD(1,2)=$lb("","child12",1)
    ^dc.childD(2,3)=$lb("","child21",2)
    ^dc.childD(2,4)=$lb("","child22",2)

    Now the data in ^dc.childD from the previous test/step is hanging in the air and cannot be accessed via SQL

Based on the above, the answer to your question will depend on what and how exactly you changed in your classes.

PS: for simplicity, I would advise you to create a clone of your dc.child class (without Relationship) and already take the "disappeared" data from it. After linking the tables (possibly with subsequent copying of data from the old Storage to the new one), the clone with the data can be deleted.

Followers:
Following:
Vitaliy has not followed anybody yet.
Global Masters badges:
Vitaliy has no Global Masters badges yet.