[an error occurred while processing this directive] [an error occurred while processing this directive]


プログラミング
逆引き
クライアントとの通信
VisMでの通信
Factoryでの通信
WebServiceでの通信
CSP (Cache' Server Pages)
Cache'SQL
設定・性能


【広告】









Managed ProviderでVB.Netから接続する


.NetからCache'のオブジェクトにアクセスする方法として、Managed Providerを使用する方法があります。

Managed Providerを使用するには
 1. Cache'側でクラスを作成する
 2. そのクラスにアクセスするためのプロキシクラスを自動生成する
 3. .Net環境でプロキシクラスを使用する
という3ステップでCache'クラスを操作できます。

ここではこのManaged Providerを使用してVB.NetからCache'クラスにアクセスする方法を記します。

目次
クラスの作成
Cache'への接続
データにアクセスする
SQL文の実行
データを追加・変更・削除する
Mコードの実行

クラスの作成

まずCache'でクラスを作成します。
/// Test Class for .Net
Class DotNet.Test Extends (%Persistent,%Populate)
{

/// 名前
Property Name As %String;
Index NameIndex On Name;

/// 日付
Property Day As %Date;
Index DayIndex On Day;

/// メモ
Property 
Memo As %String(MAXLEN = 65535);
}


データを作成します。Populateを使い10件のデータを作成しています。


Cache'への接続

C:\Intersystems\Cache\Dev\dotnet\bin\CacheNetWizard.exe を実行し、プロキシクラス定義を生成します。

1.    のConnectボタンを押し、Cache'クラス情報を取得するサーバ・ネームスペースを指定します。

2.    出力タイプをSource File, Languageを開発言語に合わせて選択します。

3.    プロキシクラスの出力先を指定します。

4.    対象となるCache'のクラスを指定します。

5.     

6.    Generateボタンを押してプロキシクラス定義ファイルを生成します。


作成されたプロキシクラス定義ファイルは以下のようになります。


Visual Studio を起動し、メニューからファィル→新しいプロジェクトを選択します。  表示されたダイアログから、Windowsアプリケーションを選択します。


空のフォームが作成されます。ボタンを1つ配置しプロパティを以下のように設定します。

.Name    btn接続
.Text      接続


このボタンのonClickメソッドとして以下の処理を記述します。

Public Class Form1

 

    Private Sub btn接続_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn接続.Click

 

        Try

            'Cache接続オブジェクト

            Dim cnCache As New InterSystems.Data.CacheClient.CacheConnection

 

            '接続文字列の作成

            ' Server = <server>; Port=<port>; Log File = <log>; Namespace = <namespace>; Password = <pwd>; User ID = <user>

            cnCache.ConnectionString = "Server = localhost; Port=1972; " & _

                "Log File = cacheConnect.log; Namespace = USER;Password = ; USER ID = "

            cnCache.Open()

            Msgbox("接続OK")

 

        Catch ex As InterSystems.Data.CacheClient.CacheException

            MsgBox(ex.Message)

            Stop

        End Try

    End Sub

End Class

この例ではローカルのCache'環境に接続するだけで、データのやりとりは発生していません。実行すると、接続OKとメッセージボックスが表示されます。


接続文字列のPortを変更してみます。この状態では正しく接続できないので、Catch節でエラーハンドリングされるはずです。

            cnCache.ConnectionString = "Server = localhost; Port=19772; " & _

                "Log File = cacheConnect.log; Namespace = USER;Password = ; USER ID = "


実行してみると、正しくエラーハンドリンクされることが確認できます。

忘れないうちに、接続文字列のPortを元に戻しておきます。


接続文字列中のログファイルを確認してみます。実行ファィルの存在する場所にcacheConnect.logファイルが作成されています。



データにアクセスする

IDを指定してデータにアクセスしてみます。VB側 btn接続_Click を以下のように修正し、ID=1のデータを取得します。

    Private Sub btn接続_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn接続.Click

        'Cache接続オブジェクト

        Dim cnCache As New InterSystems.Data.CacheClient.CacheConnection

 

        Try

            '接続文字列の作成

            ' Server = <server>; Port=<port>; Log File = <log>; Namespace = <namespace>; Password = <pwd>; User ID = <user>

            cnCache.ConnectionString = "Server = localhost; Port=1972; " & _

                "Log File = cacheConnect.log; Namespace = USER;Password = ; USER ID = "

            cnCache.Open()

        Catch ex As InterSystems.Data.CacheClient.CacheException

            MsgBox(ex.Message)

            Exit Sub

        End Try

 

Try

            'ID=1を開く

            Dim tt As DotNet.Test = DotNet.Test.OpenId(cnCache, 1)

            MsgBox(" Name:" & tt.Name & vbNewLine & " Day:" & tt.Day.ToString & vbnewline & " Memo:" & tt.memo,MessageBoxButtons.OK)

 

        Catch ex As InterSystems.Data.CacheClient.CacheException

            MsgBox(ex.Message)

            Exit Sub

        End Try

 

    End Sub


実行すると次のようにデータが取得できています。



SQL文の実行

SQL文を直接実行して全てのデータを取得します。

    Private Sub btn接続_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn接続.Click

 

        'Cache接続オブジェクト

        Dim cnCache As New InterSystems.Data.CacheClient.CacheConnection

 

        Try

            '接続文字列の作成

            ' Server = <server>; Port=<port>; Log File = <log>; Namespace = <namespace>; Password = <pwd>; User ID = <user>

            cnCache.ConnectionString = "Server = localhost; Port=1972; " & _

                "Log File = cacheConnect.log; Namespace = USER;Password = ; USER ID = "

            cnCache.Open()

 

            'MsgBox("接続OK")

 

        Catch ex As InterSystems.Data.CacheClient.CacheException

            MsgBox(ex.Message)

            Exit Sub

        End Try

 

        Try

            'SQL文を直接実行Extent-> DataReader

            Dim cmd As InterSystems.Data.CacheClient.CacheCommand = DotNet.Test.Extent(cnCache)

            cmd.CommandText = "SELECT * FROM DotNet.Test"

            Dim reader As InterSystems.Data.CacheClient.CacheDataReader = cmd.ExecuteReader()

            While reader.Read()

                MsgBox(" ID:" & reader(reader.GetOrdinal("Id")) & vbNewLine & " Name:" & reader(reader.GetOrdinal("Name")) & vbNewLine & " Day:" & reader(reader.GetOrdinal("Day")) & vbNewLine & " Memo:" & reader(reader.GetOrdinal("Memo")))

            End While

 

        Catch ex As InterSystems.Data.CacheClient.CacheException

            MsgBox(ex.Message)

            Exit Sub

        End Try

 

 

    End Sub

CacheDataReaderクラスを経由してデータにアクセスするため、データを取得するのが少し煩雑になっています。
実行するとメッセージボックスが10回表示されます。


せっかくですので一覧を取得するようにしてみます。

Form1にリストビューを追加し以下のようにプロパティを設定します。

.Name    lvwTest
.View     Details

さらにlvwTestのColumnsをクリックしてColumHeaderエディタを立ち上げ、4つの列ヘッダを定義します。

1つめ

Name

clmID

Text

ID

2つめ

Name

clmName

Text

Name

3つめ

Name

clmDay

Text

Day

4つめ

Name

clmMemo

Text

Memo


接続ボタンが押されたときのコードを以下のように修正します。

    Private Sub btn接続_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn接続.Click

 

        'Cache接続オブジェクト

        Dim cnCache As New InterSystems.Data.CacheClient.CacheConnection

 

        Try

            '接続文字列の作成

            ' Server = <server>; Port=<port>; Log File = <log>; Namespace = <namespace>; Password = <pwd>; User ID = <user>

            cnCache.ConnectionString = "Server = localhost; Port=1972; " & _

                "Log File = cacheConnect.log; Namespace = USER;Password = ; USER ID = "

            cnCache.Open()

 

            btn接続.Enabled = False

        Catch ex As InterSystems.Data.CacheClient.CacheException

            MsgBox(ex.Message)

            Exit Sub

        End Try

 

        Try

            'SQL文を直接実行Extent-> DataReader

            Dim cmd As InterSystems.Data.CacheClient.CacheCommand = DotNet.Test.Extent(cnCache)

            cmd.CommandText = "SELECT * FROM DotNet.Test"

            Dim reader As InterSystems.Data.CacheClient.CacheDataReader = cmd.ExecuteReader()

            lvwTest.Items.Clear()

            While reader.Read()

                Dim li As New ListViewItem

                li.Text = reader(reader.GetOrdinal("Id")).ToString

                li.SubItems.Add(reader(reader.GetOrdinal("Name")).ToString)

                li.SubItems.Add(reader(reader.GetOrdinal("Day")).ToString)

                li.SubItems.Add(reader(reader.GetOrdinal("Memo")).ToString)

                lvwTest.Items.Add(li)

            End While

 

        Catch ex As Exception

            MsgBox(ex.Message)

            Exit Sub

        End Try

 

    End Sub

実行し接続ボタンを押すと、次のように一覧が表示されます。



データを追加・変更・削除する

いよいよデータの取得だけでなく、追加・変更・削除を行ってみます。
これまで作成したForm1の右側にテキストボックスを4つ、ボタンを3つ配置します。

それぞれ以下のように設定します。

IDテキストボックス Name txtID
Nameテキストボックス Name txtName
Dayテキストボックス Name txtDay
Memoテキストボックス Name txtMemo
MultiLine True
クリアボタン Name btnClear
Text クリア
削除ボタン Name btnDelete
Text 削除
保存 Name btnSave
Text 保存

まず一覧表示lvwTestの項目が選択された時に、追加した各テキストボックスに値が表示されるようにします。

lvwTestをダブルクリックして、lvwTest_SelectedIndexChangedイベントハンドラの記述を行います。

    Private Sub lvwTest_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lvwTest.SelectedIndexChanged

 

        If sender Is lvwTest Then

            Dim lvSender As ListView = sender

            If lvSender.SelectedItems.Count = 1 Then '1つだけ選択されているときに

                Dim strId As String = lvSender.SelectedItems.Item(0).Text

 

                MsgBox(strId)

            End If

        End If

   End Sub

動作させてみるとlvwTestで選択した項目のIDが取得できることが確認できます。


ここでCache'からデータを取得するためにbtn接続を押した際に使用したcnCacheを使用しようとすると、変数のスコープ外であるためエラーが発生します。

そのため、cnCacheをForm1内をスコープとする変数に変更します。


Imports System.ComponentModel

Public Class Form1

 

    'Cache接続オブジェクト

    Private cnCache As New InterSystems.Data.CacheClient.CacheConnection

 

    Private Sub btn<接続_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn接続.Click

        Try

            '接続文字列の作成

            ' <以下略>


あわせて、毎回InterSystems.Data.CacheClient以下の参照を簡単にするため、Importを設定します。

Imports System.ComponentModel

Imports InterSystems.Data.CacheClient

 

Public Class Form1

 

    'Cache接続オブジェクト

    Private cnCache As New CacheConnection '短くなる

Form1内のInterSystems.Data.CacheClient. は空文字列と置換しておきます。
また、Form1内変数としてDotNet.Testのインスタンス、dnTestを宣言しておきます。
これにより、Form1のコードは以下のようになります。

Imports System.ComponentModel

Imports InterSystems.Data.CacheClient

 

Public Class Form1

 

    'Cache接続オブジェクト

    Private cnCache As New CacheConnection

 

    'DotNet.Testのインスタンス

    Private dnTest As New DotNet.Test

 

    Private Sub btn接続_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn接続.Click

        Try

            '接続文字列の作成

            ' Server = <server>; Port=<port>; Log File = <log>; Namespace = <namespace>; Password = <pwd>; User ID = <user>

            cnCache.ConnectionString = "Server = localhost; Port=1972; " & _

                "Log File = cacheConnect.log; Namespace = USER;Password = ; USER ID = "

            cnCache.Open()

 

            btn接続.Enabled = False

        Catch ex As CacheException

            MsgBox(ex.Message)

            Exit Sub

        End Try

 

        Try

            'SQL文を直接実行Extent-> DataReader

            Dim cmd As CacheCommand = DotNet.Test.Extent(cnCache)

            cmd.CommandText = "SELECT * FROM DotNet.Test"

            Dim reader As CacheDataReader = cmd.ExecuteReader()

            lvwTest.Items.Clear()

            While reader.Read()

                Dim li As New ListViewItem

                li.Text = reader(reader.GetOrdinal("Id")).ToString

                li.SubItems.Add(reader(reader.GetOrdinal("Name")).ToString)

                li.SubItems.Add(reader(reader.GetOrdinal("Day")).ToString)

                li.SubItems.Add(reader(reader.GetOrdinal("Memo")).ToString)

                lvwTest.Items.Add(li)

            End While

 

        Catch ex As Exception

            MsgBox(ex.Message)

            Exit Sub

        End Try

 

    End Sub

 

    Private Sub lvwTest_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lvwTest.SelectedIndexChanged

 

        If sender Is lvwTest Then

            Dim lvSender As ListView = sender

            If lvSender.SelectedItems.Count = 1 Then '1つだけ選択されているときに

                Dim strId As String = lvSender.SelectedItems.Item(0).Text

 

                MsgBox(strId)

 

            End If

        End If

    End Sub

End Class



lvwTest_SelectedIndexChangedの続きを記述します。

  Private Sub lvwTest_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lvwTest.SelectedIndexChanged

 

        If sender Is lvwTest Then

            Dim lvSender As ListView = sender

            If lvSender.SelectedItems.Count = 1 Then '1つだけ選択されているときに

                Dim intId As Integer = CInt(lvSender.SelectedItems.Item(0).Text)

 

                Try

                    dnTest_Load(intId) 'データをロード

                    dnTest_Disp()  'dnTestの内容をForm1のテキストボックスに表示する

                Catch ex As Exception

                    MsgBox(ex.Message)

                End Try

            End If

        End If

    End Sub

 

    Private Sub dnTest_Load(ByVal id As Integer)

        '渡されたidがサーバー上に存在するか確認

        If DotNet.Test.ExistsId(cnCache, id) Then

            '存在したらdnTestにロード

            dnTest = DotNet.Test.OpenId(cnCache, id)

        Else

            Throw New ApplicationException("指定されたIDはサーバーに存在しません:" & id)

        End If

    End Sub

 

    Private Sub dnTest_Disp() 'dnTestの内容をForm1のテキストボックスに表示する

        txtID.Text = dnTest.Id

        txtName.Text = dnTest.Name

        txtDay.Text = dnTest.Day.ToString

        txtMemo.Text = dnTest.Memo

    End Sub

実行するとlvwTestの項目をクリックすると、該当するデータが右側の各テキストボックスにロードされます。


ほか、各ボタンが押されたときの処理を記述すると以下のようになります。

Imports System.ComponentModel

Imports InterSystems.Data.CacheClient

 

Public Class Form1

 

    'Cache接続オブジェクト

    Private cnCache As New CacheConnection

 

    'DotNet.Testのインスタンス

    Private dnTest As New DotNet.Test

 

 

    Private Sub btn接続_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn接続.Click

        Try

            '接続文字列の作成

            ' Server = <server>; Port=<port>; Log File = <log>; Namespace = <namespace>; Password = <pwd>; User ID = <user>

            cnCache.ConnectionString = "Server = localhost; Port=1972; " & _

                "Log File = cacheConnect.log; Namespace = USER;Password = ; USER ID = "

            cnCache.Open()

 

            btn接続.Enabled = False

        Catch ex As CacheException

            MsgBox(ex.Message)

            Exit Sub

        End Try

 

        '全データをlvwTestに表示する

        全件一覧表示()

 

    End Sub

 

    Private Sub 全件一覧表示()

        Try

            'SQL文を直接実行Extent-> DataReader

            Dim cmd As CacheCommand = DotNet.Test.Extent(cnCache)

            cmd.CommandText = "SELECT * FROM DotNet.Test"

            Dim reader As CacheDataReader = cmd.ExecuteReader()

            lvwTest.Items.Clear()

            While reader.Read()

                Dim li As New ListViewItem

                li.Text = reader(reader.GetOrdinal("Id")).ToString

                li.SubItems.Add(reader(reader.GetOrdinal("Name")).ToString)

                li.SubItems.Add(reader(reader.GetOrdinal("Day")).ToString)

                li.SubItems.Add(reader(reader.GetOrdinal("Memo")).ToString)

                lvwTest.Items.Add(li)

            End While

 

        Catch ex As Exception

            MsgBox(ex.Message)

            Exit Sub

        End Try

    End Sub

 

    Private Sub btnClear_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClear.Click

        dnTest_Clear() 'dnTestを空にする

        dnTest_Disp() 'dnTestの内容をForm1のテキストボックスに表示する

    End Sub

 

    Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click

        Try

            dnTest_Save() 'テキストボックスの内容でdnTestを保存する

            dnTest_Disp() 'dnTestの内容をForm1のテキストボックスに表示する

            全件一覧表示() '更新されたデータを一覧に反映する

        Catch ex As Exception

            MsgBox(ex.Message)

        End Try

    End Sub

 

    Private Sub btnDelete_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDelete.Click

        Try

            dnTest_Kill() '選択されている項目を削除する

            dnTest_Clear() 'dnTestを空にする

            dnTest_Disp() 'dnTestの内容をForm1のテキストボックスに表示する

            全件一覧表示() '削除されたデータを一覧に反映する

        Catch ex As Exception

            MsgBox(ex.Message)

        End Try

    End Sub

 

    Private Sub lvwTest_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lvwTest.SelectedIndexChanged

 

        If sender Is lvwTest Then

            Dim lvSender As ListView = sender

            If lvSender.SelectedItems.Count = 1 Then '1つだけ選択されているときに

                Dim intId As Integer = CInt(lvSender.SelectedItems.Item(0).Text)

 

                Try

                    dnTest_Load(intId) 'データをロード

                    dnTest_Disp()  'dnTestの内容をForm1のテキストボックスに表示する

                Catch ex As Exception

                    MsgBox(ex.Message)

                End Try

            End If

        End If

    End Sub

 

    Private Sub dnTest_Load(ByVal id As Integer)

        '渡されたidがサーバー上に存在するか確認

        If DotNet.Test.ExistsId(cnCache, id) Then

            '存在したらdnTestにロード

            dnTest = DotNet.Test.OpenId(cnCache, id)

        Else

            Throw New ApplicationException("指定されたIDはサーバーに存在しません:" & id)

        End If

    End Sub

 

    Private Sub dnTest_Disp() 'dnTestの内容をForm1のテキストボックスに表示する

        txtID.Text = dnTest.Id

        txtName.Text = dnTest.Name

        txtDay.Text = dnTest.Day.ToString

        txtMemo.Text = dnTest.Memo

    End Sub

 

    Private Sub dnTest_Clear() 'dnTestを空にする

        If dnTest.IsConnected Then dnTest.Dispose() '接続中なら切断する

        dnTest.Init(cnCache, "DotNet.Test")

    End Sub

 

    Private Sub dnTest_Save() 'テキストボックスの内容でdnTestを保存する

        dnTest.Name = txtName.Text

        dnTest.Day = txtDay.Text

        dnTest.Memo = txtMemo.Text

        Dim sc As InterSystems.Data.CacheTypes.CacheStatus

        sc = dnTest.Save()

        If Not sc.IsOK Then '失敗した場合

            Throw New ApplicationException("保存に失敗しました:" & sc.Message)

        End If

    End Sub

 

    Private Sub dnTest_Kill()

        Dim id As String = dnTest.Id

        If dnTest.IsConnected Then dnTest.Dispose() '接続中なら切断する

 

        If id <> "" Then

            Dim sc As InterSystems.Data.CacheTypes.CacheStatus

            sc = DotNet.Test.DeleteId(cnCache, id)

            If Not sc.IsOK Then '失敗した場合

                Throw New ApplicationException("削除に失敗しました:" & sc.Message)

            End If

        End If

    End Sub

 

End Class


これで新規・更新・削除といった一通りの処理が行えるようになりました。



Mコードの実行

最後に、VisMの時と同様に$Hの値を取得してみます。

Cache'のクラス定義に$Hを返すクラスメソッド、GetHoroを追加します。

/// Test Class for .Net
Class DotNet.Test Extends (%Persistent, %Populate)
{

///
名前
Property Name As %String;

Index NameIndex On Name;

///
日付
Property Day As %Date;

Index DayIndex On Day;

///
メモ
Property Memo As %String(MAXLEN = 65535);

/// $H
を返す
ClassMethod GetHoro() As %String
{
   Q $H
}

}


クラス定義が変わったので、プロキシクラス定義もアップデートする必要があります。

C:\Intersystems\Cache\Dev\dotnet\bin\CacheNetWizard.exe を実行し、プロキシクラス定義を生成します。

前回と同様に指定し、プロキシクラス定義ファイルを生成します。

作成された定義ファィルをVisual Studioに反映させると、DotNet.Test以下にGetHoroメソッドが追加されています。

以下のように記述すると、

    Private Sub btnHoro_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnHoro.Click

        MsgBox(DotNet.Test.GetHoro(cnCache))

    End Sub

$Hの値が取得できることが確認できます。

クラスメソッドを経由すれば、既存ルーチンも問題なく取り扱えそうです。




※本記述は Cache' 2008.2 / Visual Studio 2005 SP1 における動作です。バージョンによっては動作が記述と異なることがあります。



[an error occurred while processing this directive] [an error occurred while processing this directive]
2012/11/19Update