記事
· 2020年7月27日 13m read

Cache Active X Bindingを利用したシステムをIRISに移行する方法

初めに

Caché ActiveX Bindingは、Visual Basicでクライアント・サーバー型のアプリケーション開発を支援するためにInterSystemsが提供してきたツールです。

CacheActiveX.dllとCacheObject.dllの2種類のバージョンが存在します。

IRISでは、CacheActiveX.dllは動作可能です。

CacheObject.dllはサポートしていません。

いずれにしろ誕生から既に20年以上が経過した非常に古いテクノロジーでマイクロソフト社も非推奨の古い規格ですので、今後も使い続けるのは得策ではありません。

Caché ActiveX Bindingの機能はIRISに用意されている.Net Native APIと.Net Managed Providerの機能を使って書き換え可能です。

ここでは、Caché ActiveX Bindingを使って書かれていたサンプルアプリケーションをIRISで動作するように移植した作業内容について解説します。

このサンプルは、以下のgithubサイトから入手可能です。

ADBKサンプル
 

ADBKアプリケーション

このサンプルアプリケーションは、20年以上も前にVB6サンプルとして作成されました。
 

VB6プロジェクトを.Netプロジェクトに変換
 

この作業は、VisM.OCXを利用したアプリケーションをIRISに移行する方法という記事にも同じ内容が記載されていますので、そちらをご参考ください。

VisM.OCXを利用したアプリケーションをIRISに移行する方法
 

CacheObject.dllの参照
 

Visual Studioを起動すると右側に表示されるソリューションエクスプローラーから参照の部分を開きます。

CacheObjectというのが見えるので、それを選択して、右クリックのメニューから削除をクリックします。
 

アプリケーション修正
 

それでは、IRISで動作するようにサンプルアプリケーションを修正していきましょう。

 

参照の追加

 

IRIS Native APIと.Net Managed Providerを利用するためにIRISの.Netライブラリーの参照を追加します。

プロジェクトメニューから参照の追加をクリックして参照ボタンを押して以下のファイルを選択します。

c:\intersystems\IRIS\dev\dotnet\bin\v4.5

  • InterSystems.Data.Gateway64.exe
  • InterSystems.Data.IRISClient.dll

 

ADBKMain.vbの修正

 

それではADBKMain.vbの修正を行いましょう。

先ほど参照設定したライブラリーをImportします。

Option Explicit Onの後ろに以下の行を追加します。
 

Imports InterSystems.Data.IRISClient
Imports InterSystems.Data.IRISClient.ADO


class宣言の後ろの変数宣言の所を以下のように変更します。
 

    Dim iris As IRIS
    Dim iris_object As IRISObject
    Dim iris_conn As IRISConnection = New IRISConnection
    'Dim m_factory As CacheObject.Factory
    'Dim m_object As CacheObject.ObjInstance
    'Const m_classname As String = "User.ADBK"
    Const iris_classname As String = "User.ADBK"


CacheObjectの関連の変数をIRIS関連の変数に置き換えます。
IRISの場合は、サーバーとの通信のコネクションが別オブジェクトになっているため追加の変数設定が必要です。

次にフォームのロード処理の修正を行います。
 

    'm_factory = CreateObject("CacheObject.Factory")
    iris_conn.ConnectionString = "Server = localhost; Log File=cprovider.log;Port=1972; Namespace=USER; Password = SYS; User ID = _system;"
    iris_conn.Open()
    iris = IRIS.CreateIRIS(iris_conn)


IRISの場合は、まずコネクションオブジェクトを作成する必要があります。
そして、そのConnectionStringプロパティにサーバー接続に必要な情報を設定します。
次にOpen()メソッドで接続を確立します。
接続が確立したら、IRISのインスタンスを生成します。
CacheObjectではFactoryと呼んでいたものと同等のものとなります。
 

    'sdir = m_factory.ConnectDlg
    'If sdir <> "" Then
    'm_factory.Connect(sdir)


CacheObjectの場合は、接続情報が指定されていない場合は、接続情報を尋ねるダイアログボックスが表示されていましたが、
IRISのコネクションオブジェクトにはその機能がないので、すべてコメントアウトします。

次に新規ボタンが押された時の処理を変更しましょう。

CmdNew_Clickの処理になります。

以下のように書き換えます。
 

    iris_object = iris.ClassMethodObject(iris_classname, "%New")
    If iris_object Is Nothing Then
        MsgBox("新しいオブジェクトを作成できません。")
    End If
    'm_object = m_factory.New(m_classname)
    'If m_object Is Nothing Then
    'MsgBox("新しいオブジェクトを作成できません。")
    'End If


CacheObjectの場合は、FactoryのNewメソッドで新しいオブジェクトの生成を行いましたが、
IRISでは、ClassMethodObjectメソッドで第一パラメータで指定したクラスのクラスメソッド%Newメソッドを呼び出すように変更します。

%Newメソッドは、OREFを返すので、ClassMethodObjectメソッドを使います。
ClassMethodXXXは、戻り値のタイプ別に用意されています。

次に保存ボタンが押された時の処理を変更します。

CmdUpdate_Clickの処理になります。
 

        'm_object.sys_Save()
        iris_object.Invoke("%Save")


インスタンスメソッドを呼び出す方法は、InVokeメソッドでパラメータに呼び出すメソッドの名前を指定します。

次に削除ボタンが押された時の処理を変更します。

CmdDelete_Clickの処理になります。
 

        'm_object.sys_DeleteId(id)
        iris_object.Invoke("%DeleteId", id)


同様にInVokeメソッドを呼び出すように変更します。

次に検索ボタンが押された時の処理を変更します。

CmdFind_Clickの処理になります。
 

    'm_object = FindByName.ShowDialog_Renamed(m_factory)
    iris_object = FindByName.ShowDialog_Renamed(iris, iris_conn)


検索用のダイアログを表示する際に渡すパラメータを追加する必要がありました。
コネクションオブジェクトを追加で渡す必要があります。
また戻り値もIris_objectに変更します。

次に CmdUpdate_Clickの処理を変更します。
 


            'UPGRADE_WARNING: オブジェクト m_object.ANAME の既定プロパティを解決できませんでした。 詳細については、'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="6A50421D-15FE-4896-8A1B-2EC21E9037B2"' をクリックしてください。
            'm_object.ANAME = TxtNAME.Text
            iris_object.Set("ANAME", TxtNAME.Text)
            'UPGRADE_WARNING: オブジェクト m_object.ASTREET の既定プロパティを解決できませんでした。 詳細については、'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="6A50421D-15FE-4896-8A1B-2EC21E9037B2"' をクリックしてください。
            'm_object.ASTREET = TxtADDRESS.Text
            iris_object.Set("ASTREET", TxtADDRESS.Text)
            'UPGRADE_WARNING: オブジェクト m_object.AZIP の既定プロパティを解決できませんでした。 詳細については、'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="6A50421D-15FE-4896-8A1B-2EC21E9037B2"' をクリックしてください。
            'm_object.AZIP = TxtZIP.Text
            iris_object.Set("AZIP", TxtZIP.Text)
            'UPGRADE_WARNING: オブジェクト m_object.ABTHDAY の既定プロパティを解決できませんでした。 詳細については、'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="6A50421D-15FE-4896-8A1B-2EC21E9037B2"' をクリックしてください。
            'm_object.ABTHDAY = TxtDOB.Text
            iris_object.Set("ABTHDAY", TxtDOB.Text)
            'UPGRADE_WARNING: オブジェクト m_object.APHHOME の既定プロパティを解決できませんでした。 詳細については、'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="6A50421D-15FE-4896-8A1B-2EC21E9037B2"' をクリックしてください。
            'm_object.APHHOME = TxtTELH.Text
            iris_object.Set("APHHOME", TxtTELH.Text)
            'UPGRADE_WARNING: オブジェクト m_object.APHOTH1 の既定プロパティを解決できませんでした。 詳細については、'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="6A50421D-15FE-4896-8A1B-2EC21E9037B2"' をクリックしてください。
            'm_object.APHOTH1 = TxtTELO.Text
            iris_object.Set("APHWORK", TxtTELO.Text)
            On Error GoTo actionSaveError
            'UPGRADE_WARNING: オブジェクト m_object.sys_Save の既定プロパティを解決できませんでした。 詳細については、'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="6A50421D-15FE-4896-8A1B-2EC21E9037B2"' をクリックしてください。
            'm_object.sys_Save()
            iris_object.Invoke("%Save")

 

IRISObjectでは、プロパティに直接アクセスができず代わりにSetメソッドで設定する必要があります。

また保存は、インスタンスメソッドの%Save()をInvokeメソッドで起動します。


これでADBKMain.vbの修正は終了です。


FindByNme.vbの修正


続いてFindByNme.vbの内容を変更していきましょう。
まずはIRISライブラリーのインポートが必要です。

Option Explicit Onの後ろに以下の行を追加します。
 

Imports InterSystems.Data.IRISClient
Imports InterSystems.Data.IRISClient.ADO


次に変数宣言の所を以下のように変更します。
 

    'Dim RS As CacheObject.ResultSet
    'Dim m_factory As CacheObject.Factory
    'Dim m_object As CacheObject.ObjInstance
    Dim iris As IRIS
    Dim iris_object As IRISObject
    Dim iris_conn As IRISConnection
    'Const m_classname As String = "User.ADBK"
    Const iris_classname As String = "User.ADBK"


IRISにはResultSetオブジェクトがありませんので、代替の方法で処理する必要があります。
詳細は、後程説明します。

次にShowDialog_Renamed関数の処理を変更します。

これはADBKMainから検索ボタンを押したときに呼ばれる処理になります。
 

    'Public Function ShowDialog_Renamed(ByRef factory As CacheObject.Factory) As CacheObject.ObjInstance
    Public Function ShowDialog_Renamed(ByRef iris_factory As IRIS, ByRef iris_connection As IRISConnection) As IRISObject


パラメータとしてiris_connectionを追加する必要があるので、追加します。
 

    'm_factory = factory
    iris = iris_factory
    iris_conn = iris_connection


コネクションオブジェクトの設定を追加します。
 

    'Set m_factory = Nothing
    'ShowDialog_Renamed = m_object
    ShowDialog_Renamed = iris_object


戻り値をIRISObjectを返すように変更します。

次に検索ボタンが押された時の処理を変更します。

CmdFind_Clickの処理になります。
 

    'RS = m_factory.ResultSet("User.ADBK", "ByName")
    'RS.Execute(TxtSNAME.Text) ' ByName takes a single argument
    Dim SQLtext As String = "call sqluser.ADBK_byname(?)"
    Dim Command As IRISCommand = New IRISCommand(SQLtext, iris_conn)
    Dim Name_param As IRISParameter = New IRISParameter("Name_col", IRISDbType.NVarChar)
    Name_param.Value = TxtSNAME.Text
    Command.Parameters.Add(Name_param)
    Dim Reader As IRISDataReader = Command.ExecuteReader()

 

    While Reader.Read()
        ListLookupName.Items.Add(Reader.Item(Reader.GetOrdinal("ANAME")))
    End While
    Reader.Close()
    Command.Dispose()

 

    ' 取得した名前リストをListBoxに展開
    'While RS.Next
    'UPGRADE_WARNING: オブジェクト RS.GetDataByName() の既定プロパティを解決できませんでした。 詳細については、'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="6A50421D-15FE-4896-8A1B-2EC21E9037B2"' をクリックしてください。
    'ListLookupName.Items.Add(RS.GetDataByName("ANAME"))
    'End While


IRISではResultSetメソッドがありませんので、代替手段で書き換えます。
クラスクエリーはSQLのcall文で置き換え可能です。
但し、サーバー側のクエリー定義にsqlProc属性をつける必要があります。
 

Query ByName(Name As %String) As %SQLQuery(CONTAINID = 1) [ SqlProc ]


IRISCommandオブジェクトとIRISDataReaderオブジェクトを使用してクエリーを処理します。
パラメータは、IRISParameterオブジェクトを使って定義します。

このあたりは、MicrosoftのADO.NETの仕様に基づき実装されているので、詳細はドキュメントを確認してください。

次にOKボタンが押された時の処理を変更します。

CmdOK_Clickの処理になります。
 

    'name_Renamed = VB6.GetItemString(ListLookupName, ListLookupName.SelectedIndex)
    name_Renamed = ListLookupName.Items(ListLookupName.SelectedIndex).ToString()


これはIRIS対応とは関係ないのですが、動作しなかったので、変更しました。
VB6との互換性がない部分だと想定しています。
 

    'RS = m_factory.DynamicSQL("SELECT * FROM ADBK WHERE ANAME = ?")
    'RS.Execute(name_Renamed) ' 値を'?'にバインド
    'RS.Next()
    Dim SQLtext As String = "SELECT * FROM ADBK WHERE ANAME = ?"
    Dim Command As IRISCommand = New IRISCommand(SQLtext, iris_conn)
    Dim Name_param As IRISParameter = New IRISParameter("Name_col", IRISDbType.NVarChar)
    Name_param.Value = name_Renamed
    Command.Parameters.Add(Name_param)
    Dim Reader As IRISDataReader = Command.ExecuteReader()
    Reader.Read()


先ほどと同様にIRISCommandとIRISDataReaderを使って書き換えます。
 

    'id = RS.GetDataByName("AID")
    id = Reader.Item(Reader.GetOrdinal("AID"))


フィールドの値の取得もさきほどと同様に書き換えます。
 

    'm_object = m_factory.OpenId(m_classname, id)
    'If m_object Is Nothing Then
    iris_object = iris.ClassMethodObject(iris_classname, "%OpenId", id)
    If iris_object Is Nothing Then


次は、検索の結果取得されたidを使って、オブジェクトインスタンスをオープンする処理もClassMethodObjectメソッドを
使って実装します。
 

        'CType(ADBKMain.Controls("TxtNAME"), Object).Text = m_object.ANAME
        CType(ADBKMain.Controls("TxtNAME"), Object).Text = iris_object.Get("ANAME") 
        'CType(ADBKMain.Controls("TxtZIP"), Object).Text = m_object.AZIP
        CType(ADBKMain.Controls("TxtZIP"), Object).Text = iris_object.Get("AZIP") 
        'CType(ADBKMain.Controls("TxtADDRESS"), Object).Text = m_object.ASTREET
        CType(ADBKMain.Controls("TxtADDRESS"), Object).Text = iris_object.Get("ASTREET")
        'CType(ADBKMain.Controls("TxtTELH"), Object).Text = m_object.APHHOME
        CType(ADBKMain.Controls("TxtTELH"), Object).Text = iris_object.Get("APHHOME") 
        'CType(ADBKMain.Controls("TxtTELO"), Object).Text = m_object.APHOTH1
        CType(ADBKMain.Controls("TxtTELO"), Object).Text =iris_object.Get("APHWORK")   
        'CType(ADBKMain.Controls("TxtAGE"), Object).Text = m_object.AAGE
        CType(ADBKMain.Controls("TxtAGE"), Object).Text = iris_object.Get("AAGE")
        'CType(ADBKMain.Controls("TxtDOB"), Object).Text = m_object.ABTHDAY
        CType(ADBKMain.Controls("TxtDOB"), Object).Text = iris_object.InvokeString("ABTHDAYLogicalToOdbc", iris_object.Get("ABTHDAY"))


IRISObjectでは、プロパティに直接アクセスができず代わりにGetメソッドで取得する必要があります。

DOB(誕生日)は、内部値($Horolog)をODBC形式の日付に変換する処理を加えています。


以上で修正は終了です。

 

最後に

 

既存の資産を生かしつつ、ActiveX Bindingを使用したアプリケーションの移行が簡単にできるということをご理解いただき、アプリケーションの移行にチャレンジしていただきたいと思います。

 

もう一つ、サーバー側の処理は全く修正していない点も強調しておきたいと思います。

ディスカッション (0)2
続けるにはログインするか新規登録を行ってください