Zen OLE DB プロバイダーによるプログラミング
Zen OLE DB プロバイダーを使用するためのプログラミング概念
以下のトピックでは、アプリケーション開発で Zen OLE DB プロバイダーを使用する方法について説明します。
データベースへの接続
OLE DB プロバイダーを使用する場合の一般的な疑問は、データベースへの接続方法です。このセクションでは、OLE DB プロバイダーを使用した接続の基本事項について説明します。
OLE DB プロバイダーへの接続
接続文字列
"Provider=PervasiveOLEDB;Data Source=(データベース名またはデータ ファイルへのパス)"
接続とオープンの例
Private Sub Form_Load()
Dim cn As New ADODB.Connection
Dim rs As New ADODB.Recordset
' これは、特に Client Cursor Engine を使用する場合を除き、
' 常に adUseServer です。
cn.CursorLocation = adUseServer
cn.ConnectionString = "Provider=PervasiveOLEDB;Data Source=Demodata"
cn.Open
rs.Open "Billing", cn, adOpenDynamic, adLockOptimistic, adCmdTableDirect
rs.MoveFirst
MsgBox "最初の Student ID:" & rs.Fields("Student_ID")
rs.Close
cn.Close
End Sub
その他の作業
その他の一般的な処理については、第
3 章
ADO/OLE DB リファレンス情報を参照してください。
リモート接続
プロバイダーはネットワーク プロトコルを介してデータベース エンジンに接続します。サーバー側のデータベース エンジンがリクエストを処理し、そのデータをプロバイダーに戻します。プロバイダーは ODBC クライアントと同じプロトコルを使用して、必要な処理を行ってクライアントにデータを渡します。
サポートされる新しい構文
接続文字列内で Location= パラメーターを使用してリモート サーバーを指定できます。
Provider=PervasiveOLEDB;Data Source=MyDBName;Location=MyServer
メモ:Data Source パラメーターは DSN ではなく、データベース名(DBName)を指します。DSN は ODBC でのみ使用します。
以前のバージョンとの互換性
現在、接続文字列で DDF へのパスを使用している場合はこのメソッドでもサポートします。
Provider=PervasiveOLEDB;Data Source=f:\mydata
以前のバージョンの Zen とは異なり、本リリースでは接続するサーバーにデータベース名が存在している必要があります。
データベース名を指定した場合と Location を指定した場合、あるいはマップされたドライブを指定した場合でもパフォーマンスに違いはありません。ただし、リモート サーバーに接続する方法としては Location の使用を推奨しています。OLE DB プロバイダーでは、マップされたドライブまたは UNC パスを使用した場合にアクセス権の問題が発生する可能性があります。
排他的カーソル
ほかのクライアントがレコードのロックに遭遇する可能性が高くなるリスクを負っても、作成するアプリケーションで確実に更新を行うことを優先する必要がある場合は排他的カーソルを使用します。
以前のバージョンの Zen OLE DB プロバイダーでは、排他的カーソルを使用できる ADO パラメーター adLockPessimistic がサポートされていませんでした。
現在は、このパラメーターを Zen の接続文字列の拡張機能と共に使用して排他的カーソルを持つアプリケーションを作成することができます。
OLE DB 仕様と排他的カーソル
OLE DB 仕様では排他的カーソルを、「最新のフェッチによって単一行に行われた変更が並行性違反のために失敗しないことを保証するカーソル」として定義しています。レコード セットを開いた後、バッチ更新されるまではしばらく時間がかかります。排他的カーソルを使用することは、この時間のギャップのために発生する並行性の問題を軽減する 1 つの方法です。
プロバイダーごとに行レベルのロックの実装が異なるので、OLE DB 仕様の排他的カーソルの定義は意図的に明確にされていません。 ここでは一般的な 2 つの実装について説明します。
•(a)読み取り時に行をロックする
•(b)更新の開始時に行をロックする
たとえば、次のように連続したイベントがあるとします。
1 クライアント A がレコード セットを開く
2 クライアント A が行を読み込む(a)
3 クライアント A がフィールド 1 を変更する(b)
4 クライアント A がフィールド 2 を変更する
5 クライアント A がその行を更新する
開発者から見た場合の 2 つアルゴリズムの違いは、アルゴリズム(a)では読み取りロックを使用し、アルゴリズム(b)では更新ロックを使用しているという点です。次の表では、これら 2 つのアルゴリズム間の動作の違いについてまとめています。
表 1 読み取りロックと更新ロック
ロック タイプ | 動作 |
---|
読み取りロック | 読み取るたびに行をロックします。 最初の Move メソッドで行のロックを解除します。 次の行をロックします。 |
更新ロック | データが変更されたときに行をロックします。 Update メソッドを呼び出したときに行のロックを解除します。 |
読み取りロックを使用することで、開発者は行を読み込んだときに並行性エラーを懸念することなく確実に更新を行うことができます。 ただし、これは読み取る行を常にロックします。更新ロックではデータが変更された場合に行をロックするだけです。ただし、並行性エラーが発生するのはより遅くなる可能性があります。
このアーキテクチャの変更の詳細については、
OLE DB プロバイダーのアーキテクチャを参照してください。
排他的カーソルの構文
Zen の排他的カーソルの実装によって、希望する動作を選択することができます。接続文字列内の排他的カーソルに関するパラメーターは次のとおりです。
•読み取りロックまたは更新ロック(Pessimistic Read Lock=True/False)
Open メソッドの間に、この接続文字列オプションと、排他的カーソルを指定する ADO パラメーター adLockPessimistic を併用します。
読み取りロックと更新ロックの指定
接続文字列内で Pessimistic Read Lock=True を使用すると、読み取りロックを実行します。次にそのサンプル接続文字列を示します。
"Provider=PervasiveOLEDB;Data Source=Demodata;Pessimistic Read Lock=True"
更新ロックを実行する場合は、Pessimistic Read Lock の値を False に変更します。
排他的カーソルの動作のまとめ
次の表では、排他的カーソル オプションを使用する効果についてまとめています。
表 2 排他的ロックのオプションとその動作のマトリックス
Pessimistic Read Lock= | 動作 |
---|
True | 読み取り時にレコードをロックします。 既にロックされていた場合はエラーを返します。 |
False | 更新時にレコードをロックします。 既にロックされていた場合はエラーを返します。 |
排他的カーソルを使った Visual Basic サンプル コード
次の Visual Basic サンプル コードの一部では、読み取りロックの排他的カーソルを使用して DEMODATA サンプル データベースの Course テーブルを開きます。
Public myRecordSet as ADODB.Recordset
myRecordSet.CursorLocation = adUseServer
myConnString = "Provider=PervasiveOLEDB;Data Source=DEMODATA;Pessimistic Read Lock=True"
myRecordSet.Open "Course",myConnString, adOpenDynamic, adLockPessimistic, adCmdTableDirect
myRecordSet.MoveFirst
プログラミングの注意事項
次のセクションでは、OLE DB プロバイダーに関する注意事項を述べます。
更新の表示
adCmdTableDirect を使ってテーブルに行った更新は、コマンドベースのレコード セットから見ることができます。
たとえば、次のように連続したイベントがあるとします。
•adCmdTableDirect を使用し、トランザクショナル(Btrieve)方式でテーブルを開く。
•テーブルに変更を加え、Update メソッドを呼び出す。
•次に、トランザクショナル方式で行われたテーブルの更新によって変更されたデータを選択する SQL クエリを実行する。
このような状況では、トランザクショナル方式で行った更新は SQL クエリに表示されます。
UNC パスまたはマップされたドライブを使う OLE DB プロバイダーの使用
ここでは、接続文字列内で OLE DB プロバイダーを使用し、マップされたドライブまたは UNC パスを Data Source 部分に指定したときに起こる状況について説明します。たとえば、次のようにします。
Provider=PervasiveOLEDB;Data Source=\\servername\path
以前のバージョンのプロバイダーでは、この接続文字列が自動的に正しいデータベース名に解決されました。現在のプロバイダーを使用すると、この設定でアクセス権の問題が発生する可能性があります。接続文字列内で新しい Location パラメーターを使用する場合は、アクセス権の問題は発生しません。Location パラメーターの詳細については、
リモート接続を参照してください。
クライアントがサーバーに接続しようとしたときに、そのクライアントのデータ ソースが UNC パスの場合、プロバイダーはそのパスをデータベース名とサーバー名に解決しなければなりません。OLE DB プロバイダーがこの情報を取得するには、クライアントのユーザー アカウントにそのサーバーの管理者または Power User の権限がなければいけません。
多くの構成において、クライアントのユーザー アカウントにはこれらの必要なアクセス権がない場合があります。クライアントが必要な権限を持っていない場合、OLE DB プロバイダーでは図
3 のようなダイアログを表示します。ユーザーはこのダイアログでデータベース名とサーバー名を入力することができます。
図 3 データベース名とサーバー名を解決するダイアログ
[
上記の設定をレジストリに保存しますか?]のチェックをオンにすると、そのエントリは Windows レジストリに保存されるので、ここで参照した UNC またはマップされたドライブの場所を対象とするダイアログ(図
3)はそれ以降表示されません。その代わりに、データベース名はレジストリを使って解決され、これによりパフォーマンスが向上します。使用されるレジストリの場所は次のとおりです。
SOFTWARE\Actian\Zen\OLEDB\Connections
開発者がこのダイアログをエンド ユーザーに見せないようにする場合は、Windows のレジストリに必要な情報を入力することができます。上記のキーの下位に次の書式で入力します。
名前 | 値 |
---|
データへの UNC パス | サーバー名;データベース名 |
たとえば、次のようにします。
名前 | 値 |
---|
\\myserver\c\pvsw\demodata | myserver;demodata |
必要であれば、同じデータベース名を指す複数の UNC エントリを持つことができます。
ADO Refresh メソッドのサポート例
以下に、パラメーター クエリとストアド プロシージャを使用した ADO Refresh メソッドの例を示します。
パラメーター クエリを使用した例
connstr = "Provider=PervasiveOLEDB;Data Source=Demodata"
cn.Open connstr
cmd.ActiveConnection = cn
cmd.CommandType = adCmdText
cmd.CommandText = "Select * From Room where Building_Name = ?"
'パラメーターを最新の情報に更新
cmd.Parameters.Refresh
cmd.Parameters(0).Value = "Bartold Building"
cmd.Execute
ストアド プロシージャを使用した例
connstr = "Provider=PervasiveOLEDB;Data Source=Demodata"
cn.Open connstr
'ストアド プロシージャの呼び出し
cmd.ActiveConnection = cn
cmd.CommandText = "PROCOUT"
cmd.CommandType = adCmdStoredProc
cmd.Parameters.Refresh
cmd.Execute
Debug.Print cmd.Parameters(0).Value
静的カーソルでの Seek
静的カーソルで Seek を使用するには、結果セットを開く前にインデックスを設定しておく必要があります。たとえば、次のようにします。
Dim rs AsNew ADODB.Recordset
rs.Index = "segment"
rs.Open "Simple", "Provider=PervasiveOLEDB;Data Source=MyData", adOpenStatic, adLockOptimistic, adCmdTableDirect
rs.Seek Array(2, 9)
rs.Close
リモート接続
OLE DB プロバイダーは、リモート接続を作成することはできません。 つまり、接続文字列内でリモート サーバーを設定することができません。 ただし、同じ機能を実行する代わりの方法があります。
•Zen プロバイダーでテスト済みの RDS を使用します。
•COM+ サービスを使用してビジネス オブジェクトを開発し、CreateObject を使用してオブジェクトを作成します。たとえば、次のようにします。
Dim m_busObj As projDLL.busObj
rs As New ADODB.Recordset
Set m_busObj = CreateObject("sampProj2.TwoPhaseSampleProduct", "RemoteServer")
Set rs = m_busObj.GetData()
テーブル定義
ITableDefinition は以下の列の作成をサポートしませんが、これはその基盤となる Zen エンジンがサポートしていないためです。
•BSTR
•WCHAR
•VarWChar
•LongVarWChar
•UserDefined Types
•GUID
デフォルトのロック タイプ
LockType を指定しないと、カーソルは即時更新モードに設定されます。 これにより、いくつかの影響があります。
•すべての変更はすぐにデータベースに転送されます(Update を呼び出す必要がありません)。
•Update および UpdateBatch は実際には意味を持ちません(データベースは既に更新されているため)。ただし、Supports メソッドは Update に対しては True を返しますが、UpdateBatch には False を返します。
•GetOriginalValue は使用できません。
GetOriginalValue が使用可能かどうかをプログラムで調べるには、"Supports" メソッドの引数として adUpdateBatch を使用する必要があります。 たとえば、次のようにします。
if rs.Supports(adUpdateBatch) then
someValue = rs.fields(iCol).OriginalValue
end if
初期化プロパティ
次の表は、OLE DB の初期化で Zen がサポートするプロパティと、それに対応する接続文字列識別子の一覧です。
表 3 接続文字列識別子
接続文字列識別子 | プロパティ |
---|
Cache Authentication | DBPROP_AUTH_CACHE_AUTHINFO |
Connect Timeout | DBPROP_INIT_TIMEOUT |
Data Source | DBPROP_INIT_DATASOURCE |
Encrypt Password | DBPROP_AUTH_ENCRYPT_PASSWORD |
Locale Identifier | DBPROP_INIT_LCID |
Location | DBPROP_INIT_LOCATION |
Password | DBPROP_AUTH_PASSWORD |
Persist Encrypted | DBPROP_AUTH_PERSIST_ENCRYPTED |
Persist Security Info | DBPROP_AUTH_PERSIST_SENSITIVE_AUTHINFO |
User ID | DBPROP_AUTH_USERID |
以下のプロパティを設定することもできます。
•DBPROP_INIT_HWND
•DBPROP_INIT_PROMPT
•DBPROP_INIT_ASYNCH
•DBPROP_INIT_OLEDBSERVICES
COM+ サービスのサポート
このセクションでは、OLE DB プロバイダーが Microsoft の COM+ サービスとどのように相互作用するかについて説明します。
COM+ サービスとは
COM+(Component Object Model)サービスは Microsoft 固有の技術で、マルチ スレッド コンテキスト内のビジネス オブジェクトを作成するのに使用されます。COM+ は主に Visual Basic プログラマのためにデザインされましたが、それに限定されません。COM+ を使用すると、多階層型アプリケーションを迅速に作成できます。また COM+ は、本来ならば開発者が実装する必要のある多くの利点を備えています。次に COM+ の利点を挙げます。
•コンテキスト
•同時実行
•セキュリティ強化
•オブジェクト プーリング
•ジャスト イン タイム アクティベーション
•キュー コンポーネント
•イベント
COM+ の詳細については、Microsoft のドキュメントを参照してください。
COM+ サービスは、MTS(Microsoft Transaction Server)によってもたらされる利点の拡張です。MTS は Microsoft の以前のビジネス オブジェクト サーバーの実装です。概して、(Microsoft および Zen のドキュメントにある)MTS への参照は、COM+ サービスと置き換えることができます。
OLE DB プロバイダーは COM+ サービスでサポートされます。 COM+ サービス内で行われる ADO 呼び出しはその他すべての ADO クライアント呼び出しと同様に動作します。
Visual Basic プログラマのための COM+ サービスの例
Visual Basic プログラマは、MTSTransactionMode プロパティに通じている必要があります。このプロパティを NoTransactions 以外に設定すると、Microsoft トランザクションが起動されます。この機能の詳細については COM+ サービスのドキュメントを参照してください。
次の例は、Microsoft Transaction Server の使い方を示しています。GetObjectContext の呼び出しを成功させるには、MTSTransactionMode プロパティを NoTransactions 以外のどれかに設定する必要があります。Microsoft Transactions を使用すると、Microsoft Transaction Coordinator が 2 フェーズ コミットを行えるようになります。
Public Function UpdatePayroll(employeeID As Integer, salary As Currency)
On Error GoTo ErrHandler
Dim rs As New ADODB.Recordset
rs.Index = "employeeID"
rs.Open "PayrollTable", "Provider=PervasiveOLEDB;Data Source=CompanyDB", adOpenDynamic, adLockOptimistic, adCmdTableDirect
rs.Seek employeeID, adSeekFirstEQ
If rs.EOF = True Then
GetObjectContext.SetAbort
Else
rs!salary = salary
End If
rs.Update
rs.Close
rs = Nothing
GetObjectContext.SetComplete
Exit Function
ErrHandler:
GetObjectContext.SetAbort
If Not IsNull(rs) Then
If rs.State = adStateOpen Then
rs.Close
End If
End If
rs = Nothing
End Function
一方、接続オブジェクトを使用する ADO トランザクションを使って、このビジネス オブジェクトを書き直すことができます。そうすると、MTSTransactionMode プロパティを NoTransactions に設定できるようになります。Microsoft Transactions を使用しなければ、2 フェーズ コミットのオーバーヘッドはなくなります。また、トランザクションをサポートしないオブジェクトはメモリに常駐させることができるのに対し、トランザクションをサポートするオブジェクトは参照されるたびに構築され破壊されます。
Public Function UpdatePayroll(employeeID As Integer, salary As Currency)
On Error GoTo ErrHandler
Dim cn As New Connection
Dim rs As New ADODB.Recordset
cn.Open "Provider=PervasiveOLEDB;Data Source=CompanyDB"
cn.BeginTrans
rs.Index = "employeeID"
rs.Open "PayrollTable", cn, adOpenDynamic, adLockOptimistic, adCmdTableDirect
rs.Seek employeeID, adSeekFirstEQ
If rs.EOF = True Then
cn.RollbackTrans
Else
rs!salary = salary
End If
rs.Update
rs.Close
cn.CommitTrans
Exit Function
ErrHandler:
cn.RollbackTrans
If Not IsNull(rs) Then
If rs.State = adStateOpen Then
rs.Close
End If
End If
End Function
Execute メソッド(ADO コマンド)
Zen OLE DB プロバイダーを使用している場合、Command オブジェクトの Execute メソッドでは、操作の種類に基づいて RecordsAffected パラメーターが異なる結果を返します。
SELECT オペレーション
SELECT ステートメントを実行している場合、RecordsAffected は -1(マイナス 1)を返し、このオプションがサポートされていないことを示します。 たとえば、次のようにします。
cn.Open "Provider=PervasiveOLEDB;Data Source=TestData;"
SQLst = "Select * From MyData"
cmd.ActiveConnection = cn
cmd.CommandText = SQLst
Set rs = cmd.Execute(RecordsAffected)
この場合、RecordsAffected は -1 になります。
SELECT クエリが返すレコード数を取得したい場合は、次の例のように RecordCount プロパティを使用します。
recordcount = rs.RecordCount
' Mydata のレコード数
バッチ挿入、更新および削除
RecordsAffected は、バッチ挿入、更新および削除を実行したときに、オペレーションが影響した正確なレコード数を返します。
例 - バッチ挿入
cn.Open "Provider=PervasiveOLEDB;Data Source=TestData;"
SQLst = "Insert into MyData(utinyint_, usmallint_, uinteger_, ubigint_, char_, character_, bit_) Values (1, 12, 13, 100, 'testdata', 'chardata', 1)"
cmd.ActiveConnection = cn
cmd.CommandText = SQLst
cmd.Execute RecordsAffected
この場合、RecordsAffected は 1 になります。
例 - バッチ更新
SQLst = "Update MyData set char_ = 'SampleTest' where uinteger_ = 13"
cmd.ActiveConnection = cn
cmd.CommandText = SQLst
cmd.Execute RecordsAffected
この場合、RecordsAffected は 13 という値を持つすべてのレコード数に相当する x になります。