Question Emanuel Lazar · 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

Comments

Stefan Rieger · Jul 7, 2021

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)

0
Emanuel Lazar  Jul 11, 2021 to Stefan Rieger

can you advice with code example, step-by-step

how to generate the proxy class, and then how I use it in .Net environment

0
Stefan Rieger · Jul 12, 2021
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;
    }
0
Stefan Rieger  Jul 12, 2021 to Stefan Rieger

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)

0
Emanuel Lazar  Jul 12, 2021 to Stefan Rieger

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"

0
Stefan Rieger  Jul 12, 2021 to Emanuel Lazar

just implemented  a small testClass to show what i mean:

0
Stefan Rieger  Jul 12, 2021 to Stefan Rieger
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();
    }
    
}
0
Stefan Rieger  Jul 12, 2021 to Stefan Rieger

and testmethod to get an impression what's going on:

0
Stefan Rieger  Jul 12, 2021 to Stefan Rieger
[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");

    }
    
}
0
Emanuel Lazar  Jul 12, 2021 to Stefan Rieger

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 ?

0
Stefan Rieger  Jul 13, 2021 to Emanuel Lazar

i'm not sure if i understood rigth - your'e talking about a event listener on a database field change? (keep in mind, that the properties content is a database field which potentially could be changed by cos, sql or even direct global access)?

0
Emanuel Lazar  Jul 13, 2021 to Stefan Rieger

now I ask, only on .myProperty (in class) string change

can I "listen" to specific ^Global change or Node change ?

0
Stefan Rieger  Jul 13, 2021 to Emanuel Lazar

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

0
Emanuel Lazar  Jul 13, 2021 to Stefan Rieger

I ask, only on .myProperty (in class) string change

I can trigger this event , with .Net Notify ?

how is the code syntax for that ?

I have done it On older Cache .net provider

0
Stefan Rieger  Jul 13, 2021 to Emanuel Lazar

i'm not sure if understood correctly, but for .net this normally is done like that:

0
Stefan Rieger  Jul 13, 2021 to Stefan Rieger
public class TestClass : INotifyPropertyChanged
{
    
    public event PropertyChangedEventHandler PropertyChanged;

    public string Test
    {
        set
        {
            if (_test != value)
            {
                _test = value;
                PropertyChanged?.Invoke(this, nameof(Test));
            }
                
        }
        get
        {
            return _test;
        }
    }
    string _test;

}
0
Emanuel Lazar  Jul 14, 2021 to Stefan Rieger

Hi Stefan,

1.

yes , it's much closer, I'll check if it's actually fires the event.

2. each property\method definition in class I'll have to make the  wrap on iris get/set (no connection to event)?

3. get method arguments byRef from the irisClass ?

did not see any doc about, can it be done ?

0
Stefan Rieger  Jul 14, 2021 to Emanuel Lazar

the first two might be a bit off topic - this points more or less to .net architectural decisions. if you want email  me  directly (s-rieger@gmx.net) and i try to give you some hints.

3.: Did not look into that deep - do you have an example on which method you really need that?

0