ODP.NetとOO4O
来源:互联网 发布:做微课需要什么软件 编辑:程序博客网 时间:2024/05/31 19:36
oo4o:Oracle Objects for OLE
最主要的区别就是
ODP.Net是非接续型(数据库自动接续,自动切断)
oo4o是接续型
はじめに
「意外と簡単!? .NETでOracle」シリーズが.NET開発者でオラクルを利用したい方のシステム構築の一助になれば幸いです。
「意外と簡単!? .NETでOracle」シリーズは以下の3つの構成を予定しています。
- スマートクライアント編
- Web アプリケーション編「ASP.NET」
- oo4o(Oracle Objects for OLE)からODP.NET移行編(本書)
- ODP.NETにするメリット
- oo4oとODP.NET アーキテクチャの違い
- oo4oとODP.NET コネクションの違い
- データアクセスの違い
- PL/SQL連携方法についての違い
- トランザクション制御についての違い
- ADOからの移行
- PL/SQLの完全なサポート
- ネイティブなOracleデータ型のサポート
- LOB型、REF CURSOR、DATE型など
- 接続プーリング
- 配列バインド
- グローバリゼーション
- Unicodeの完全サポート
- トランザクション
- XML DBのサポート
- 透過的アプリケーション・フェイルオーバー(TAF)
図1 RCWについて
ODP.NETとoo4oの違いをまとめると、以下のようになります。
■ODP.NETとoo4oの違い
ODP.NEToo4oOracleネイティブなドライバーCOMサーバーであるデータ・アクセスにブリッジが入らないRCWによるデータ変換等のオーバヘッドが発生するOracle固有の機能のサポートOracle固有の機能のサポート
図2 非接続型でのデータアクセス
- コネクションプーリングの動作
- 非接続型でのデータベースへの自動接続/自動切断
図3 C/Sアプリケーションでのデータアクセス
図4 WEBアプリケーションでのデータアクセス
ADO.NETでのデータベースへの接続はコネクションプールがデフォルトで有効になっており、ADO.NETに準拠したODP.NETも同様にコネクションプールはデフォルトで有効になっております。oo4oでコネクションプールを利用する場合には、明示的にコネクションプールを有効にするためのコーディングが必要になります。具体的には、OraSessionオブジェクトのCreateDatabasePoolメソッドをコールします。
リスト.1 oo4oでのコネクションプールの利用
Set OraSession = CreateObject("OracleInProcServer.XOraSession")
‘Databaseとの接続を管理するOraDatabaseオブジェクト
OraSession.CreateDatabasePool 2, 40, 200, "ORCL", "SCOTT/TIGER", 0
‘サービス名、ユーザーID、パスワードを指定してOraDatabaseオブジェクトを生成
Set OraDatabase = OraSession.GetDatabaseFromPool(100)
ODP.NETでは、以下のコードのように、Oracleデータベースへの接続に最低限必要な接続文字列情報、User ID/Password/Data Sourceの指定のみで、コネクションプールが有効になります。
Imports Oracle.DataAccess.Types
Public Class fmMainMenu
Inherits System.Windows.Forms.Form
(略)
Private Sub DbConnect()
Dim conn As New OracleConnectio
conn.ConnectionString = "Data Source=orcl;User id=scott;Password=tiger"
conn.Open()
End Sub
コネクションプールで使用する接続文字列属性とデフォルト値は以下のようになっております。
表2 コネクションプールに関する接続文字列属性
ODP.NETでコネクションプールを明示的に有効にするには、OracleConnectionオブジェクトのConnectionStringプロパティの接続文字列属性で設定します。
リスト.3 ODP.NETでのコネクションプールの利用(デフォルトで有効)
‘コネクションプールを明示的に設定
conn.ConnectionString = "User Id=SCOTT;Password=TIGER; Data Source=ORCL;” & _
"Pooling=True;Min Pool Size=2;Max Pool Size=50"
conn.Open()
コネクションプールは、接続プーリング・サービスによって、プールを一意に識別するためのシグネチャとしてConnectionStringを使用して作成されます。シグネチャとしてConnectionStringは大文字・小文字も区別します。例えば、以下のような接続文字列ですと、Data Sourceの指定が小文字と大文字で違うので、それぞれに別々のコネクションプールが作成されてしまいます。
リスト.4 コネクションプールの生成単位
"User Id=scott;Password=tiger;Data Source=ORCL"
コネクションプール以外に、Oracleへの接続に関して、ODP.NETはoo4oにはない以下の固有の機能があります。
tnsname.oraを使用しない接続
リスト.5 TNSNAMES.ORAのネットサービス名の例
ORCL =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = orcl)
)
)
tnsnames.oraファイルは、クライアント毎に配置する必要があり(Webアプリケーションの場合は、IISがクライアントとなる)、多数のクライアントが存在する場合、そのファイルを配布するのも大変ですし、そのファイルに変更が必要になった場合は、さらに大変です。ODP.NETでは、通常であれば、tnsnames.oraファイルに記述する内容をアプリケーション・コード内に記述することが可能です。
リスト.6 tnsname.oraを使用しない接続
Dim conn As New OracleConnection
Dim sb As New System.Text.StringBuilder
sb.Append("User Id=scott; Password=tiger;")
sb.Append("Data Source=(DESCRIPTION = (ADDRESS_LIST = ")
sb.Append("(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)")
sb.Append("(PORT = 1521)))(CONNECT_DATA = (SERVER = DEDICATED)")
sb.Append("(SERVICE_NAME = ORCL)));")
conn.ConnectionString = sb.ToString
conn.Open()
conn.Close()
オペレーティング・システム認証と特権接続
ConnectionString属性のUser Idを” / “に設定することにより、データベース・ユーザーの認証にWindowsユーザー・ログイン資格証明を使用できます。また、DBA Privilege属性を介してSYSDBA権限またはSYSOPER権限のいずれかを使用してOracleデータベースに接続できます。
リスト.7 オペレーティング・システム認証と特権接続
Dim cnn As New OracleConnection
‘認証にWindowsユーザー・ログイン資格証明を使用し、DBA Privilege属性に「SYSDBA」を指定
cnn.ConnectionString = "User Id=/;Data Source=orcl;DBA Privilege=SYSDBA"
cnn.Open()
MsgBox("Connect OK!!")
cnn.Close()
パスワードの期限切れ
Oracleユーザーのパスワードが期限切れだった場合、新しいパスワードで接続をオープンすることが可能です。
リスト.8 パスワードの期限切れ
Dim cnn As New OracleConnection
cnn.ConnectionString = _
"User Id=scott;Password=tiger;Data Source=ora10g"
Try
cnn.Open()
Catch
cnn.OpenWithNewPassword("panther")
End Try
図5 oo4oとODP.NETで使用するオブジェクトの比較
oo4oからODP.NETへ移行した際に、「接続型データアクセス」と「非接続型データアクセス」でコードにどのような違いがあるのかを説明します。
接続型データアクセスでの比較
図6 接続型でのoo4oとODP.NETで使用するオブジェクトの比較
上記のオブジェクトを使用したコードをそれぞれ比較してみましょう。oo4oからemp表の値を取得し、デバックウィンドウに結果を表示するコードは以下のようになります。
リスト.9 oo4oでのデータの取得サンプル
‘OraDynasetオブジェクトを生成
Set OraDynaset = _
OraDatabase.CreateDynaset("SELECT empno,ename FROM emp", ORADYN_READONLY)
‘デバックウィンドウに値を表示
Do Until OraDynaset.EOF
Debug.Print OraDynaset.Fields("empno").Value + " / " + _
OraDynaset.Fields("ename").Value
OraDynaset.MoveNext
Loop
上記のコードをODP.NETを使用したコードにすると以下のようになります。
リスト.10 ODP.NETでのデータの取得サンプル(接続型)
conn.ConnectionString = _
"User ID=scott;Password=tiger;Data Source=orcl"
conn.Open()
Dim cmd As New OracleCommand
‘CommandTextにSQLを設定する。
cmd.Connection = conn
cmd.CommandText = "select empno, ename from emp"
‘OracleCommandオブジェクトのExecuteReaderメソッドを実行して、OracleDataReaderオブジェクトを生成
Dim rdr As OracleDataReader
rdr = cmd.ExecuteReader
‘デバックウィンドウに値を表示
Do While rdr.Read
Debug.WriteLine(CStr(rdr("empno")) + " / " + _
rdr("ename"))
Loop
‘接続をClose
rdr.Close()
cmd.Close()
以上のように、接続型でのデータアクセスに関しては、oo4oとODP.NETは類似しております。一つ違いがあるとすれば、oo4oでは、SQLを発行した結果セットを「OraDynaset」に直接格納しているのに対して、ODP.NETでは「OracleCommand」を経由してSQLを発行し、結果セットをOracleDataReaderで取得しています。次に、更新処理の違いを比較してみます。
リスト.11 oo4oでのデータの更新サンプル(接続型)
Dim OraDatabase As Object
Set OraSession = CreateObject("OracleInProcServer.XOraSession")
Set OraDatabase = OraSession.OpenDatabase("orcl", "scott/tiger", &H2&)
‘更新SQLの発行
OraDatabase.ExecuteSQL "update emp set ename='scott' where empno=6"
リスト.12 ODP.NETでのデータの更新サンプル
Dim cmd As New OracleCommand
cmd.Connection = conn
‘更新SQLの発行
cmd.CommandText = "update emp set ename='Bob' where empno=6"
cmd.CommandType = CommandType.Text
cmd.ExecuteNonQuery()
上記のように、ODP.NETはデータの取得/更新時には必ずOracleCommandを使用します。後程説明する、非接続型データアクセス使用時にもOracleCommandの使用は必須になります。一般的にデータを更新する方法に関しては、SQLを直接発行する方法と、結果セットに対してフィールド単位で値を設定し更新する方法の2つがあります。oo4oではOraDynaset使用し、以下のコードのようにフィールド指定でのデータの更新が可能です。
リスト.13 oo4oでのデータの更新サンプル(フィールド指定)
"orcl", "scott/tiger", dbOption.ORADB_DEFAULT)
sSql = "SELECT * FROM MstCustomer Where CustomerId='" + TextCustomerId.Text + "'"
Set OraDynaset = _
OraDatabase.CreateDynaset(sSql, ORADYN_DEFAULT)
OraDynaset.Edit
OraDynaset("CustomerID") = TextCustomerId.Text
OraDynaset("CustomerNAME") =TextCustomerName.Text
OraDynaset("EmployeeNAME") = TextEmployeeName.Text
OraDynaset("kana") = TextKana.Text
OraDynaset("job") = TextJob.Text
OraDynaset("postcode") = TextPostCode.Text
OraDynaset("prefectures") = ComboPrefectures.Text
OraDynaset("address") = TextAddress.Text
OraDynaset("tel") = TextTel.TextOraDynaset("fax") = TextFax.Text
OraDynaset("note") = TextNote.Text
OraDynaset.Updates
しかし、ODP.NETの接続型データアクセスで利用するOracleDataReaderは読み取り専用であるため、上記のようなフィールドを指定した更新が出来ません。ODP.NETでは、非接続型データアクセスを使用してフィールドを指定した更新が可能です。
図6 接続型でのoo4oとODP.NETで使用するオブジェクトの比較
「OracleDataAdapter」と「DataSet」オブジェクトは、非接続型データアクセスを行う場合の固有のオブジェクトになります。oo4oでは非接続型データアクセスの概念がないので、「OracleDataAdapter」と「DataSet」同様のオブジェクトはありません。では、実際にODP.NETを使用した「非接続型データアクセス」のコードを見てみましょう。「OracleDataAdapter」と「DataSet」オブジェクトは、非接続型データアクセスを行う場合の固有のオブジェクトになります。oo4oでは非接続型データアクセスの概念がないので、「OracleDataAdapter」と「DataSet」同様のオブジェクトはありません。では、実際にODP.NETを使用した「非接続型データアクセス」のコードを見てみましょう。
リスト.14 ODP.NETでのデータの取得サンプル(非接続型)
Dim cmd As New OracleCommand
Dim dsList As New DataSet
Dim iCnt As Integer
cnn.ConnectionString = _
"user id=scott;password=tiger;data source=orcl"
cmd.Connection = cnn
‘DataAdapterを使用して、結果セットをDataSetに格納
cmd.CommandText = "Select * from emp"
Dim adp As New OracleDataAdapter(cmd)
adp.Fill(dsList, "EmpList")
‘DataSetの内容をデバックウィンドウに表示
With dsList.Tables("EmpList")
For iCnt = 0 To .Rows.Count - 1
Debug.WriteLine(CStr(.Rows(iCnt).Item("empno")) + " / " + _
.Rows(iCnt).Item("ename"))
Next
End With
上記のコードは非接続型データアクセスでテーブルの情報を取得して、デバックウィンドウに表示するコードになります。DataSetに結果セットを格納するには、OracleDataAdapterのFillメソッドを使用します。逆に、DataSetの内容をOracleデータベースに書き戻す作業時にもOracleDataAdapterのUpdateメソッドを使用します。
図7 非接続型でのデータの取得/更新
「リスト.14 ODP.NETでのデータの取得サンプル(非接続型)」のコードを見ると、コネクションのオープンとクローズをおこなっていないのがわかると思います。非接続型では、OracleDataAdapterのFillメソッド、もしくはUpdateメソッドを呼び出したときに自動的にコネクションを確立し、処理が終了したら自動的にコネクションを切断します。DataSetへ値を格納後は、既にOracleデータベースとのコネクションが切れた状態になっています。このように、SQLを発行する瞬間にのみデータベースへ接続し、後の作業はデータベースへの接続が切断された状態でおこないます。このようなアクセス手法によることから、非接続型と呼ばれています。非接続型は、データベースへの接続時間を最小限にし、その結果、データベースサーバーの負荷を下げることが可能になっています。DataSetに格納された値は、OracleDataAdapterのUpdateメソッドを使用し、Oracleデータベースに更新された値を書き戻します。Updateメソッドを実行すると、OracleDataAdapterのUpdateCommand, DeleteCommand, InsertCommandに設定されたSQLが実行されます。
図8 OracleDataAdapterのUpdateメソッドをコールしたときの動作
OracleDataAdapterのUpdateCommand、DeleteCommand、InsertCommandそれぞれのSQLは個別に設定することも可能ですが、OracleCommandBuilderを使用し、SQLを自動生成することが可能です。
リスト.15 ODP.NETでのデータの更新サンプル(非接続型)
If dsCustomer.Tables("MstCustomer").Rows.Count = 0 Then
CustRow = dsCustomer.Tables("MstCustomer").NewRow()
Else
CustRow = dsCustomer.Tables("MstCustomer").Rows(0)
End If
CustRow.Item("CustomerId") = TextBoxID.Text
CustRow.Item("CustomerNAME") = TextBoxCompanyName.Text
~ 以下略 ~
If CustRow.RowState = DataRowState.Detached Then _
dsCustomer.Tables("MstCustomer").Rows.Add(CustRow)
da.Update(dsCustomer.Tables("MstCustomer"))
上記のコードではカラム名を文字列で指定しており、データ型の復元もキャストにより行われているため、実行時エラーが発生する可能性があります。これを回避するためには、型付データセットというのを使用します。型付データセットとはテーブル名や列名などの定義情報を事前に取り込むことにより作成されるデータセットになります。型付データセットを利用すると、コードの可読性が向上しますし、インテリセンスによるコード補完も行われるため、コーディングミスも軽減されます。また、コンパイル時の名前チェックを有効化することも可能です。 形なしデータセットと型付データセットのコードを比較すると、以下のようになります。
リスト.16 形なしデータセットを使用したコード
dsCustomer.Tables("MstCustomer").Rows(0).Item(“CustomerName”)
リスト.17 形付データセットを使用したコード
型付データセットの利用には、データセット定義ファイル(以下、xsdファイル)を作成する必要があります。xsdファイルは「Oracle Developer Tools for Visual Studio .NET」(以下、ODT)を使用すると簡単に作成できます。ODTのダウンロード/インストールについては、Oracle Technology Network(以下、OTN)の以下の 「.NET Developer Center」に情報が掲載されておりますので、そちらをご覧ください。以下にODTを使用してxsdファイルを作成する方法について説明します。
1. xsdファイルの新規作 Visual Studio .NETから新規のプロジェクトファイルを作成し、プロジェクトファイルを右クリック->追加->新しい項目の追加をクリックしてください。
「新しい項目の追加」ウィンドウが表示されるので、「データセット」をクリックし、「開く」ボタンをクリックします。
2. xsdファイルの作成 「Oracleエクスプローラ」から対象テーブルを選択し、新規に作成したxsdファイルのデザインウィンドウにドラッグ&ドロップすると、xsdファイルが自動的に作成されます。
3. 型付データセットの作成 ツールボックスよりデータセットを選択し、フォームに貼り付けると、以下のようにデータセットの追加ウィザードが表示されます。 上記の画面で、「型指定されたデータセット(T)」を選択し、先ほど作成したxsdファイルを選択後、「OK」ボタンをクリックすると、型付データセットが作成されます。
リスト.18 サンプルパッケージの作成
CURSOR c1 IS SELECT ename FROM emp;
TYPE empCur IS REF CURSOR RETURN c1%ROWTYPE;
PROCEDURE GetEmpData(
indeptno IN NUMBER,
EmpCursor in out empCur );
END;
CREATE OR REPLACE PACKAGE BODY SCOTT.pkg_ref AS
PROCEDURE GetEmpData(indeptno IN NUMBER,
EmpCursor in out empCur ) IS
BEGIN
OPEN EmpCursor FOR
SELECT ename FROM emp WHERE deptno=indeptno;
END GetEmpData;
END pkg_ref;
上記のPL/SQLパッケージのGetEmpDataファンクションは、emp表のdeptno列を引数で取得し、該当する結果セットをRef Cursorで取得しております。次にoo4oから上記のPL/SQLパッケージのGetEmpDataファンクションをコールするコードは以下のようになります。
リスト.19 oo4oからストアドプロシージャをコールし、Ref Cursorを取得するコード
Set OraDatabase = OraSession.OpenDatabase( _
"orcl", "scott/tiger", dbOption.ORADB_DEFAULT)
‘ deptnoをパラメータで設定
OraDatabase.Parameters.Add "DEPTNO", 10, ORAPARM_INPUT
OraDatabase.Parameters("DEPTNO").serverType = ORATYPE_NUMBER
‘GetEmpDataファンクションをコール
sSql = "Begin pkg_ref.GetEmpData(:DEPTNO, :EmpCursor); end;"
‘Ref Cursorの結果セットを取得
Set OraDynaset = OraDatabase.CreatePlsqlDynaset(sSql, "EmpCursor", 0&)‘
結果をデバックウィンドウに表示
Do While Not OraDynaset.EOF
Debug.Print OraDynaset("ename")
OraDynaset.MoveNext
Loop
ODP.NETの接続型でのコードは以下のようになります。
リスト.20 ODP.NETからストアドプロシージャをコールし、Ref Cursorを取得するコード(接続型)
Dim conn As New OracleConnection("User Id=Scott;Password=Tiger;Data Source=orcl")
conn.Open()
‘GetEmpDataファンクションをコールするSQLをOracleCommandに設定
Dim cmd As New OracleCommand("pkg_ref.GetEmpData", conn)
cmd.CommandType = CommandType.StoredProcedure
‘ deptnoをパラメータで設定
cmd.Parameters.Add("DEPTNO", 10)
cmd.Parameters.Add("empCursor", OracleDbType.RefCursor, ParameterDirection.Output)
‘GetEmpDataファンクションをコール
cmd.ExecuteNonQuery()
‘Ref Cursorの結果セットを取得
Dim dr1 As OracleDataReader = _
CType(cmd.Parameters(1).Value, OracleRefCursor).GetDataReader
‘ 結果をデバックウィンドウに表示
Do While dr1.Read
Debug.WriteLine(dr1("ename"))
Loop
Ref Cursorの結果セットの取得は、非接続型でのアクセスでも可能です。実際のコードは以下のようになります。
リスト.21 ODP.NETからストアドプロシージャをコールし、Ref Cursorを取得するコード(非接続型)
‘GetEmpDataファンクションをコールするSQLをOracleCommandに設定
Dim cmd As New OracleCommand("pkg_ref.GetEmpData", conn)
cmd.CommandType = CommandType.StoredProcedure
‘Ref Cursorの結果セットを取得
cmd.Parameters.Add("DEPTNO", 10)
cmd.Parameters.Add("empCursor", OracleDbType.RefCursor, ParameterDirection.Output)
' GetEmpDataファンクションをコールし、結果をDataSetに格納
Dim dsData As New DataSet
Dim da As New OracleDataAdapter(cmd)
da.Fill(dsData, "data")
'Gridへ表示
DataGridEmp.SetDataBinding(dsData, "data")
次に、複数のRef Cursorを取得するコードを比較してみます。実行を確認するために、テスト用のパッケージを作成します。
リスト.22 複数のRef Cursorを返すパッケージの作成
CURSOR c1 IS SELECT * FROM emp;
CURSOR c2 IS SELECT * FROM dept;
TYPE empCur IS REF CURSOR RETURN c1%ROWTYPE;
TYPE deptCur IS REF CURSOR RETURN c2%ROWTYPE;
PROCEDURE GetEmpDeptData(
EmpCursor in out empCur,
DeptCursor in out deptCur
);
END;
CREATE OR REPLACE PACKAGE BODY SCOTT.pkg_ref2 AS
PROCEDURE GetEmpDeptData(
EmpCursor in out empCur,
DeptCursor in out deptCur) IS
BEGIN
OPEN EmpCursor FOR SELECT * FROM emp;
OPEN DeptCursor FOR SELECT * FROM dept;
END GetEmpDeptData;
END pkg_ref2;
上記のPL/SQLパッケージのGetEmpDeptDataファンクションは、emp表とdept表の2つの結果セットを返すコードになります。oo4oで複数のRef Cursorの結果セットを取得するコードは以下のようになります。
リスト.23 oo4oから複数のRef Cursorを取得するコード
Dim OraSession As New OraSessionClass
Dim OraDatabase As OraDatabase
Set OraDatabase = OraSession.OpenDatabase( _
"orcl", "scott/tiger", dbOption.ORADB_DEFAULT)
OraDatabase.Parameters.Add "EmpCursor", 0, ORAPARM_OUTPUT
OraDatabase.Parameters("EmpCursor").serverType = ORATYPE_CURSOR
OraDatabase.Parameters.Add "DeptCursor", 0, ORAPARM_OUTPUT
OraDatabase.Parameters("DeptCursor").serverType = ORATYPE_CURSOR
sSql = "Begin pkg_ref2.GetEmpDeptData(:EmpCursor,:DeptCursor); end;"
Set OraSqlStmt = OraDatabase.CreateSql(sSql, ORASQL_FAILEXEC)
Set EmpDynaset = OraDatabase.Parameters("EmpCursor").Value
Set DeptDynaset = OraDatabase.Parameters("DeptCursor").Value
Do While Not EmpDynaset.EOF
Debug.Print EmpDynaset("ename")
EmpDynaset.MoveNext
Loop
Do While Not DeptDynaset.EOF
Debug.Print DeptDynaset("dname")
DeptDynaset.MoveNext
Loop
OraDatabase.Parameters.Remove ("EmpCursor")
OraDatabase.Parameters.Remove ("DeptCursor")
同様に、ODP.NETの接続型で複数のRef Cursorの結果を取得してみます。
リスト.24 ODPから複数のRef Cursorを取得するコード(接続型)
Dim cmd As New OracleCommand("pkg_ref2.GetEmpDeptData", conn)
cmd.CommandType = CommandType.StoredProcedure
'REF CURSORパラメータのバインド
cmd.Parameters.Add("EmpCursor", OracleDbType.RefCursor, ParameterDirection.Output)
cmd.Parameters.Add("DeptCursor", OracleDbType.RefCursor, ParameterDirection.Output)
cmd.ExecuteNonQuery()
'SQL文の実行とRef Cursorの使用
Dim dr1 As OracleDataReader = _
CType(cmd.Parameters(0).Value, OracleRefCursor).GetDataReader
Dim dr2 As OracleDataReader = _
CType(cmd.Parameters(1).Value, OracleRefCursor).GetDataReader
'RefCursorの内容をデバックウィンドウに表示
Do While dr1.Read
Debug.WriteLine(dr1("ename"))
Loop
Do While dr2.Read
Debug.WriteLine(dr2("dname"))
Loop
非接続型でも同様に複数のRef Cursorを取得可能です。
リスト.25 ODP.NETから複数のRef Cursorを取得するコード(非接続型)
Dim cmd As New OracleCommand("pkg_ref2.GetEmpDeptData", conn)
cmd.CommandType = CommandType.StoredProcedure
'REF CURSORパラメータのバインド
cmd.Parameters.Add("EmpCursor", OracleDbType.RefCursor, ParameterDirection.Output)
cmd.Parameters.Add("DeptCursor", OracleDbType.RefCursor, ParameterDirection.Output)
'SQL文の実行とRef Cursorの使用
Dim dsData As New DataSet
Dim da As New OracleDataAdapter(cmd)
da.Fill(dsData, "data")'
Gridへ表示
DataGridEmp.SetDataBinding(dsData, "data")
DataGridDept.SetDataBinding(dsData, "data1")
リスト.26 oo4oからのトランザクション制御
Dim OraSession As New OraSessionClass
Dim OraDatabase As OraDatabase
Set OraDatabase = OraSession.OpenDatabase( _
"orcl", "scott/tiger", dbOption.ORADB_DEFAULT)
'トランザクションの開始
OraSession.BeginTrans
OraDatabase.ExecuteSQL "insert into emp(empno,ename) values(6,'Michel')"
OraSession.CommitTrans
oo4oでは、OraSessionオブジェクトに対して、トランザクションの制御を行います。ODP.NETでは、OracleConnectionオブジェクトから、OracleConnectionのBeginTransactionメソッドを実行し、ローカル・トランザクションを開始します。
リスト.27 ODP.NETからのトランザクション制御
cnn.Open()
Dim cmd As New OracleCommand
cmd.Connection = cnn
'トランザクションの開始
Dim txn As OracleTransaction = cnn.BeginTransaction()
cmd.CommandText = "insert into emp(empno,ename) values(6,'Michel')"
cmd.CommandType = CommandType.Text
cmd.ExecuteNonQuery()
txn.Commit()
また、ODP.NETでは以下のように「SavePoint」を指定して、トランザクション内にセーブポイントを作成することが可能です。
リスト.28 ODP.NETからのトランザクション制御(SavePointの利用)
cnn.ConnectionString = "user id=scott;password=tiger;data source=orcl"
cnn.Open()
'トランザクションの開始
Dim txn As OracleTransaction = cnn.BeginTransaction()
Dim strSQL1 As String = "INSERT INTO emp (empno, ename) VALUES (1,'Employee1')"
Dim myCmd As New OracleCommand(strSQL1, cnn)
Dim res As Integer = myCmd.ExecuteNonQuery()
‘SavePoint ‘a’ でトランザクションを保存
txn.Save("a")
Dim strSQL2 As String = "INSERT INTO emp (empno, ename) VALUES (2,'Employee2')"
Dim myCmd2 As New OracleCommand(strSQL2, cnn)
Dim res2 As Integer = myCmd2.ExecuteNonQuery()
‘SavePoint ‘b’ でトランザクションを保存
txn.Save("b")
SavePoint ‘a’までロールバックしコミット
txn.Rollback("a")
txn.Commit()
上記のコードでは、コード内でトランザクションの制御をおこなっています。その他に、COM+サービスを利用した自動トランザクション機能を利用し、トランザクションの制御をおこなうことも可能です。oo4oを利用している場合、データアクセス部分をCOMコンポーネントとして作成し、コンポーネントサービスでCOMコンポーネントの登録を行い、COMコンポーネント単位でトランザクションの管理をおこないます。
登録されたコンポーネントは、コンポーネントサービスで、トランザクションサポートの設定が可能です。 図11 コンポーネントサービスでのトランザクションサポートの設定
ODP.NETでも同様にCOM+サービスを利用した自動トランザクションの制御は可能です。ODP.NETからCOM+を利用するには、Oracle Services for Microsoft Transaction Server(OraMTS)がインストールされ、適切に設定されている必要があります。COM+自体のトランザクション機能については、Microsoft社のCOM+に依存する内容であるため、Microsoft社のMSDNサイト、「.NETでCOM+ サービスを使用する」などを参照してください。
ADOからの移行
図11 ADOとODP.NETで使用するオブジェクトの比較
ADOでは、以下のコードのようにRecordSetを開いて、Movenextメソッドでシーケンシャルに読み込みながら処理を行うプログラミングスタイルが一般的だと思います。
リスト.29 ADOのRecordSetを利用したサンプルコード
~ データアクセス ~
RecordSet.Movenext
Loop
以上のコードですと、ループ処理の間はデータベースと接続された状態になっています。ODP.NETのOracleDataReaderは、ADOのRecordSetのReadOnly , FowardOnlyオプションで開いた状態に似ています。. NET環境からのデータアクセスは非接続型でのデータアクセスが主流になりますので、ADOからODP.NETへの移行も、oo4oからODP.NETの移行と同様に、非接続型でのデータアクセス手法を習得する必要があります。OracleDataAdapterを経由した、DataSetへのデータの格納と、DataSetからデータベースへのデータの書き戻しの概念を学ぶ必要があります。
図12 非接続型でのデータアクセス
しかし、既存のADOを利用して作成されたアプリケーションをODP.NETに変更するには、かなりのコードの修正が必要となります。とりあえず、最も簡単にADOを使用して作成されたアプリケーションを.NET化する方法として、Visual Studio .NETに付属している、アップグレードウィザードを使用する方法があります。アップグレードウィザードとは、Visual Basic 6.0 プロジェクトを Visual Basic .NET プロジェクトにアップグレードするツールになります。コマンドラインから、Vbupgrade.exe の引数にプロジェクトを指定することでアップグレードできますし、Visual Basic 6.0 のプロジェクトを Visual Studio .NET で開くと、自動的にウィザードが起動し、プロジェクトをアップグレードすることもできます。
図13 アップグレード ウィザードの起動
実際に、アップグレードウィザードを使用してVisual Basic 6.0 プロジェクトを Visual Basic .NET プロジェクトに変換してみましょう。まずは、Visual Basic 6.0で作成された移行元のアプリケーションを作成します。Oracleデータベースにアクセスし、Visual Besic 6.0 の DataGrid コントロールにemp表の内容を表示するアプリケーションのコードは以下のようになります。
リスト.30 アップグレードウィザードを使用して、.NET化したコード
Dim rs As ADODB.Recordset
Set conn = New ADODB.Connection
conn.CursorLocation = adUseClient
conn.ConnectionString = _
"Provider=OraOLEDB.Oracle.1;User ID=scott;Password=tiger;Data Source=orcl;"
conn.Open
Set rs = conn.Execute("SELECT * FROM emp", , adCmdText)
Set Me.DataGrid1.DataSource = rs
上記のVBで作成されたアプリケーションのプロジェクトファイルをVisual Studio .NETで開くと、アップグレードウィザードが起動し、プロジェクトをVB.NETへアップグレードできます。実際にアップグレードされたコードは以下のようになります。
リスト.31 アップグレードウィザードを使用して、.NET化したコード
Dim rs As ADODB.Recordset
conn = New ADODB.Connection
conn.CursorLocation = ADODB.CursorLocationEnum.adUseClient
conn.ConnectionString = _
Provider=OraOLEDB.Oracle.1;User ID=scott;Password=tiger;Data Source=orcl;"
conn.Open()
rs = conn.Execute("SELECT * FROM emp", , ADODB.CommandTypeEnum.adCmdText)
Me.DataGrid1.DataSource = rs
アップグレードウィザードを使った場合、データベースへのアクセスは、ADO.NET に変換されるわけではなく、ADO のラッパークラスを使って ADO のまま動作するように変換されます。また、DataGrid コントロールも Visual Basic 6.0 のコントロールがそのまま使われています。確かに、この実装でも正しく動作します。しかも開発者は殆どコードを変更することなく、Visual Basic .NET に移行することができます。しかしながら、この実装方法には、いくつか注意しなければならない点があります。ラッパークラスを返して ADO を使うことにより、オーバーヘッドが発生し、従来の Visual Basic 6.0 で作成したアプリケーションよりパフォーマンスが低下します。本来、.NET Framework が提供する ADO.NET を使用することによる、パフォーマンスの向上や、非接続型のデータアクセスと言った .NET のメリットを十分に発揮できません。上記のコードを、アップグレードウィザードを使用せずにODP.NET で実装したコードは以下のようになります。
リスト.32 ADOからODP.NETへ手動でコードを変更したサンプル
"User Id=Scott;Password=Tiger;Data Source=orcl")
Dim cmd As New OracleCommand("Select * from emp", conn)
Dim adp As New OracleDataAdapter(cmd)
Dim ds As New DataSet
adp.Fill(ds, "emplist")
DataGrid1.SetDataBinding(ds, "emplist")
コードの変更以外にも、フォームで使用しているコントロールの移行も必要になります。上記のアプリケーションは、Visual Basic 6.0で使用しているDataGridコントロールをVisual Studio .NETのDataGridコントロールに変更しています。同じDataGridコントロールでも仕様は異なりますのでご注意ください。
http://otndnld.oracle.co.jp/easy/dotnet/oo4otoodp/index.html#2
- ODP.NetとOO4O
- NET下基于OO4O,FME,ODP.NET的Oracle Spatial空间数据读取操作
- ADO.NETとODP.NET
- OO4O
- ODP.NET Types Overview
- ODP.NET vs MSDP
- ODP.NET 介绍
- 使用ODP.NET
- Oracle:ODP.NET Managed
- 在vb.net中应用OO4O
- 使用 ODP.NET 访问 Oracle
- ODP.net 安装及连接
- Oracle:ODP.NET Managed 小试牛刀
- Oracle:ODP.NET Managed 数据库连接
- ODP
- Microsoft ADO.NET 与 Oracle ODP.NET
- 如何调用Oracle PL/SQL(ODP.NET)
- 关于ODP.NET的一点说明
- 用数据说话,看Google 怎样被陷害(转)
- 用数据说话,看Google 怎样被陷害
- Head First C# 中文版 第12章 回顾与前瞻 page543
- 云计算到底能给我们带来什么
- WindowsXP 实现VPN+PPPOE+NAT 服务器
- ODP.NetとOO4O
- 独家:.NET开发人员必知的八个网站
- Zend创始人访谈:不急于升级到PHP 6
- Mac OS X: 自动绑定网络共享
- jQuery高级篇 简单几招学会如何制作jQuery插件
- OpenGL 四种测试
- 组策略自动安装证书(from gnaw0725)
- ASP 递归显示无穷树状结构, 下拉框中显示树状效果
- JavaScript Games