Question
· Jul 5, 2021

IRIS - Native API  and .NET Provider  - Have a little Regression to Cache .net Provider ?

 Native API  , IRIS 2019 regression vs Cache .Net provider 

1. checking the native API, with .net provider, from IS docs, I realize,

that it is not possible to wrap objectSricpt Class with .NET (C# for example) pure Class with it's methods/properties

and make pure instance syntax of: new myNetClass - as wrapper of irisClass.

as I realize, you can run  .Net Class , only with .Invoke or iris.ClassMethodVoid("class.name","method")

such syntax, cannot execute event driven on proprety change, let say, with it's build in mechanizm in .Net

 

2. IRIS 2019.

this version is missing the class IRISObject  ? I have to upgrade to IRIS2021 ?

Product version: IRIS 2019.1
Discussion (18)1
Log in or sign up to continue

1. like it this way; if you want "net" property access you have to generate proxy classes which wrap the mentioned methods...

2. InterSystems.Data.IRISClient.AD.IRISObject  is in Assembly InterSystems.Data.IRISClient, maybe dll not matching framework version? (umpf, sorry didn't read that you're on 2019... don't know about that)

this is taken from testlibrary - where "Appliance.User" is a custom defined Object. 
Using IRIS and invoking ClassMethod %Library.Pesistent.%OpenId to receive a ObjectReference to the stored object with ID 1. 
Using that ObjectReference i'm able to invoke %ClassName on that object to get the ClassName of that object. 
With tryBlock i'm using same extensions to invoke same helper methods wich encapsulate more classMethods from %Persistent - but that follows exactly same pattern...


using (var conn = ConnectionFactory.CreateConnection() as IRISADOConnection)
{

    var iris = IRIS.CreateIRIS(conn);
    var obj = iris.ClassMethodObject("Appliance.User", "%OpenId", 1 );
    Assert.NotNull(obj);
    
    var iObj = obj as IRISObject;
    Assert.NotNull(iObj);
    Assert.True(iObj.Oref() == "3@Appliance.User");
    
    var clsName = iObj.InvokeString("%ClassName", true );
    try
    {
        var id = iObj.InvokeString("%Id");
        iris.LockId(clsName, id);
        iris.UnLockId(clsName, id);
        
        //iris.ValidateIndex(clsName);
        iris.PurgeIndex(clsName);
        iris.BuildIndex(clsName);
        
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
        throw;
    }

so mainly you have to work with Iris Class Documentation to find details of the Method Signatures.

If it's a classMethod you can invoke the matching IRIS Method directly, if it's a InstanceMethod you have to invoke %OpenId or %New() to have a Object Handle and invoke Methods on them. 

Invoking the Methods on Iris is straight forward and not complicated - (used to be a pain with Cache); 

Be aware that RefrenceParameters and Results with .Net Interface MAY NOT correspond to IRIS Documentation - actually i can't give you a reliable advice on that.

N.B. Some method just DO NOT WORK with .Net Interface - mainly this are all Methods which produce multiple lines of output if invoked by Iris Terminal (e.g. %ValidateIndices). If i have to invoke a method like that i just wrap them into a userdefined IRIS Helper-Class and invoke this helper class. (you even might declare your user method as SQL Method beeing able to invoke this method by sql)

I think , I have difficulty to understand your example:

iris Class : 

PCG.myClass

with property:

myProperty

set objMyClass = ##class(PCG.myClass).%New()

set objMyClass.myProperty = "string Property"

in .Net :

1. I need to wrap the : PCG.myClass

2. make an instance of the myClass

3. set to .myProperty as String value, I expect syntax :

objNetMyClass.myProprty = "String Text in .Net Project"

public class TestClass : IDisposable
{

    public TestClass(IRISADOConnection conn, int idValue)
    {
        iris = IRIS.CreateIRIS(conn);
        proxy = (IRISObject)iris.ClassMethodObject("User.MyClass", "%OpenId", idValue);
        Id = idValue;
    }

    public TestClass(IRISADOConnection conn)
    {
        iris = IRIS.CreateIRIS(conn);
        proxy = (IRISObject)iris.ClassMethodObject("User.MyClass", "%New");
    }

    public void Save()
    {
        int related = 1;
        proxy.InvokeIRISStatusCode("%Save", related);
        if (!Id.HasValue)
        {
            Id = (int)proxy.InvokeLong("%Id");
        }
    }
    
    public string MyProperty
    {
        set
        {
            proxy.Set(nameof(MyProperty), value);
        }
        get
        {
            return proxy.GetString(nameof(MyProperty));
        }
    }

    internal int? Id;
    
    IRISObject proxy;
    IRIS iris;

    public void Dispose()
    {
        iris.Close();
    }
    
}
[Test]
public void pcg()
{

    using (var conn = ConnectionFactory.CreateConnection() as IRISADOConnection)
    {
        
        conn.ChangeNs("\"USER\"");
        var tc = new TestClass(conn);
        tc.MyProperty = "FuzziGagga";
        tc.Save();
        Assert.NotNull(tc.Id);
        var id = tc.Id.Value;

        tc = new TestClass(conn, id);
        var myProp = tc.MyProperty;
        Assert.True(myProp == "FuzziGagga");

    }
    
}

Hi Stefan,

1. this example looks, much better. and I understand your example.

you actually wrap property values set/get with Iris native commands get/set

2. now I want to add to this : .myProperty event handler,

so if .myProperty changed (in objectscript) I want to add in .Net notify listener

to fire  event with .Net syntax ,

how can I do it ?

yes, that sounds for me like tracing to the database writer - i'm not aware of this functionality in any database at all. 

keep in mind that changing a database field depends on several factors - if you're in a transaction  it might look for the client who's running the update like the field is changed, for others not; If transaction fails the field content will be rolled back.

the "normal" way is just to poll the property regularly to see if it's been changed