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アプリケーション
このサンプルアプリケーションは、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.ADO
class宣言の後ろの変数宣言の所を以下のように変更します。
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の場合は、サーバーとの通信のコネクションが別オブジェクトになっているため追加の変数設定が必要です。
次にフォームのロード処理の修正を行います。
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と呼んでいたものと同等のものとなります。
'If sdir <> "" Then
'm_factory.Connect(sdir)
CacheObjectの場合は、接続情報が指定されていない場合は、接続情報を尋ねるダイアログボックスが表示されていましたが、
IRISのコネクションオブジェクトにはその機能がないので、すべてコメントアウトします。
次に新規ボタンが押された時の処理を変更しましょう。
CmdNew_Clickの処理になります。
以下のように書き換えます。
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の処理になります。
iris_object.Invoke("%Save")
インスタンスメソッドを呼び出す方法は、InVokeメソッドでパラメータに呼び出すメソッドの名前を指定します。
次に削除ボタンが押された時の処理を変更します。
CmdDelete_Clickの処理になります。
iris_object.Invoke("%DeleteId", id)
同様にInVokeメソッドを呼び出すように変更します。
次に検索ボタンが押された時の処理を変更します。
CmdFind_Clickの処理になります。
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.ADO
次に変数宣言の所を以下のように変更します。
'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 iris_factory As IRIS, ByRef iris_connection As IRISConnection) As IRISObject
パラメータとしてiris_connectionを追加する必要があるので、追加します。
iris = iris_factory
iris_conn = iris_connection
コネクションオブジェクトの設定を追加します。
'ShowDialog_Renamed = m_object
ShowDialog_Renamed = iris_object
戻り値をIRISObjectを返すように変更します。
次に検索ボタンが押された時の処理を変更します。
CmdFind_Clickの処理になります。
'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()
ListLookupName.Items.Add(Reader.Item(Reader.GetOrdinal("ANAME")))
End While
Reader.Close()
Command.Dispose()
'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属性をつける必要があります。
IRISCommandオブジェクトとIRISDataReaderオブジェクトを使用してクエリーを処理します。
パラメータは、IRISParameterオブジェクトを使って定義します。
このあたりは、MicrosoftのADO.NETの仕様に基づき実装されているので、詳細はドキュメントを確認してください。
次にOKボタンが押された時の処理を変更します。
CmdOK_Clickの処理になります。
name_Renamed = ListLookupName.Items(ListLookupName.SelectedIndex).ToString()
これはIRIS対応とは関係ないのですが、動作しなかったので、変更しました。
VB6との互換性がない部分だと想定しています。
'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 = Reader.Item(Reader.GetOrdinal("AID"))
フィールドの値の取得もさきほどと同様に書き換えます。
'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 = 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を使用したアプリケーションの移行が簡単にできるということをご理解いただき、アプリケーションの移行にチャレンジしていただきたいと思います。
もう一つ、サーバー側の処理は全く修正していない点も強調しておきたいと思います。