目次
「意外と簡単!? .NETでOracle」シリーズは、Microsoft Visual Studio.NETを使用してOracle10g対応アプリケーションをこれから開発されるかた向けに作成しております。.NETからオラクルへの接続にはさまざまな方法が存在しますが、「意外と簡単!? .NETでOracle」シリーズではオラクル社が提供している Oracle Data Provider for .NETを利用しており、開発言語はVisual Basic.NETを使用しております。今回は「oo4o(Oracle Objects for OLE)からODP.NET移行編」ということで、今までVisual Basic(4,5,6)とoo4oを利用してアプリケーションを開発されていたかたむけに、どのようにして既存のアプリケーションを.NET対応するかを説明します。
「意外と簡単!? .NETでOracle」シリーズが.NET開発者でオラクルを利用したい方のシステム構築の一助になれば幸いです。
Oracle Data Provider for .NET(ODP.NET)はMicrosoft .NET環境(以下、.NET)からOracleデータベースへの最適なデータ接続を提供するミドルウェアです。OLE DB .NETやODBC .NETと違い、ODP.NETはデータアクセスのブリッジを経由しないネイティブ設計なので、最も効率的かつ高機能なデータベース接続を提供します。 また、ODP.NETはOracleに特化しているデータプロバイダであり、以下の固有の機能を実装しています。
ODP.NETとoo4oの違いをまとめると、以下のようになります。 ■ODP.NETとoo4oの違い
oo4oとODP.NETではOracleへのデータアクセス方法が大きく異なります。その中でも最も大きな違いは、ADO.NET(ODP.NETはADO.NETに準拠しています)から採用された、非接続型でのデータアクセス方式です。非接続型の特長としては、DataAdapter 経由でメモリ内の DataSet を利用します。したがって、Oracleデータベースとの接続が切れている状態でもデータにアクセスが可能です。
逆に、接続型とはCommand オブジェクトを利用し、SQLコマンドを直接発行するようになります。したがって、処理が終了するまでOracleとの接続を維持しなければなりません。oo4oには非接続型でのデータアクセスの概念がありませんので、oo4oからODP.NETへデータプロバイダを変更する際には、新たにこの非接続型でのデータアクセス手法を理解する必要があります。非接続型でのデータアクセス手法の詳細は、「3. データアクセスの違い」で説明します。
アプリケーションがOracleデータベースを使用してSQLを実行するためには、OracleデータベースにSQL文を渡す手段が必要です。このとき、アプリケーションとOracleデータベースを結ぶSQL実行の通信路が必要になります。この通信路のことを「コネクション」と言います。oo4oとODP.NETのコネクションの大きな違いは、以下の2つが挙げられます。
ADO.NETでのデータベースへの接続はコネクションプールがデフォルトで有効になっており、ADO.NETに準拠したODP.NETも同様にコネクションプールはデフォルトで有効になっております。oo4oでコネクションプールを利用する場合には、明示的にコネクションプールを有効にするためのコーディングが必要になります。具体的には、OraSessionオブジェクトのCreateDatabasePoolメソッドをコールします。 リスト.1 oo4oでのコネクションプールの利用 ‘OraSessionClassをオブジェクト化して、OracleInProcServerとの接続を確立する。
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の指定のみで、コネクションプールが有効になります。 リスト.2 ODP.NETでのコネクションプールの利用(デフォルトで有効)
Imports Oracle.DataAccess.Client
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でのコネクションプールの利用(デフォルトで有効) Dim conn As OracleConnection = New OracleConnection
‘コネクションプールを明示的に設定 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" "User Id=scott;Password=tiger;Data Source=ORCL"
コネクションプール以外に、Oracleへの接続に関して、ODP.NETはoo4oにはない以下の固有の機能があります。
接続文字列属性のOracleへの接続文字列には、「Data Source」として、データベースの場所とデータベース・サービスの名前を示す接続記述子を指定します。具体的にはtnsnames.oraファイルに記述されているネット・サービス名です。
リスト.5 TNSNAMES.ORAのネットサービス名の例 ORCL = tnsnames.oraファイルは、クライアント毎に配置する必要があり(Webアプリケーションの場合は、IISがクライアントとなる)、多数のクライアントが存在する場合、そのファイルを配布するのも大変ですし、そのファイルに変更が必要になった場合は、さらに大変です。ODP.NETでは、通常であれば、tnsnames.oraファイルに記述する内容をアプリケーション・コード内に記述することが可能です。 リスト.6 tnsname.oraを使用しない接続 Dim conn As New OracleConnection
ConnectionString属性のUser Idを” / “に設定することにより、データベース・ユーザーの認証にWindowsユーザー・ログイン資格証明を使用できます。また、DBA Privilege属性を介してSYSDBA権限またはSYSOPER権限のいずれかを使用してOracleデータベースに接続できます。 リスト.7 オペレーティング・システム認証と特権接続 Dim cnn As New OracleConnection
Oracleユーザーのパスワードが期限切れだった場合、新しいパスワードで接続をオープンすることが可能です。 リスト.8 パスワードの期限切れ Dim cnn As New OracleConnection
ODP.NETは、ADO.NETに準拠したデータプロバイダであり、ADO.NETと同じように「接続型データアクセス」と「非接続型データアクセス」を利用してOracleデータベースのデータを取得することが可能です。oo4oでは「非接続型データアクセス」という概念がなく、どちらかというと「接続型データアクセス」に近いアクセスモデルになります。oo4oとODP.NETで使用するオブジェクトを比較すると、以下のようになります。
oo4oからODP.NETへ移行した際に、「接続型データアクセス」と「非接続型データアクセス」でコードにどのような違いがあるのかを説明します。
oo4oとODP.NETの「接続型データアクセス」で使用するオブジェクトの比較は以下のようになります。
「非接続型データアクセス」で使用するODP.NETのオブジェクトは以下のようになります。
「OracleDataAdapter」と「DataSet」オブジェクトは、非接続型データアクセスを行う場合の固有のオブジェクトになります。oo4oでは非接続型データアクセスの概念がないので、「OracleDataAdapter」と「DataSet」同様のオブジェクトはありません。では、実際にODP.NETを使用した「非接続型データアクセス」のコードを見てみましょう。「OracleDataAdapter」と「DataSet」オブジェクトは、非接続型データアクセスを行う場合の固有のオブジェクトになります。oo4oでは非接続型データアクセスの概念がないので、「OracleDataAdapter」と「DataSet」同様のオブジェクトはありません。では、実際にODP.NETを使用した「非接続型データアクセス」のコードを見てみましょう。 リスト.14 ODP.NETでのデータの取得サンプル(非接続型) Dim cnn As New OracleConnection
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メソッドを使用します。
「リスト.14 ODP.NETでのデータの取得サンプル(非接続型)」のコードを見ると、コネクションのオープンとクローズをおこなっていないのがわかると思います。非接続型では、OracleDataAdapterのFillメソッド、もしくはUpdateメソッドを呼び出したときに自動的にコネクションを確立し、処理が終了したら自動的にコネクションを切断します。DataSetへ値を格納後は、既にOracleデータベースとのコネクションが切れた状態になっています。このように、SQLを発行する瞬間にのみデータベースへ接続し、後の作業はデータベースへの接続が切断された状態でおこないます。このようなアクセス手法によることから、非接続型と呼ばれています。非接続型は、データベースへの接続時間を最小限にし、その結果、データベースサーバーの負荷を下げることが可能になっています。DataSetに格納された値は、OracleDataAdapterのUpdateメソッドを使用し、Oracleデータベースに更新された値を書き戻します。Updateメソッドを実行すると、OracleDataAdapterのUpdateCommand, DeleteCommand, InsertCommandに設定されたSQLが実行されます。
OracleDataAdapterのUpdateCommand、DeleteCommand、InsertCommandそれぞれのSQLは個別に設定することも可能ですが、OracleCommandBuilderを使用し、SQLを自動生成することが可能です。 リスト.15 ODP.NETでのデータの更新サンプル(非接続型) Dim CustRow As DataRow
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 形なしデータセットを使用したコード Dim strCustName As String = _ dsCustomer.Tables("MstCustomer").Rows(0).Item(“CustomerName”) リスト.17 形付データセットを使用したコード Dim strCustName As String = dsCustomer.MstCustomer(0).CustomerName
型付データセットの利用には、データセット定義ファイル(以下、xsdファイル)を作成する必要があります。xsdファイルは「Oracle Developer Tools for Visual Studio .NET」(以下、ODT)を使用すると簡単に作成できます。ODTのダウンロード/インストールについては、Oracle Technology Network(以下、OTN)の以下の 「.NET Developer Center」に情報が掲載されておりますので、そちらをご覧ください。以下にODTを使用してxsdファイルを作成する方法について説明します。
oo4oとODP.NETでのPL/SQL連携の違いについて見てみましょう。まずは、以下のSQLを実行し、PL/SQLパッケージを作成します。
リスト.18 サンプルパッケージの作成 CREATE OR REPLACE PACKAGE SCOTT.pkg_ref AS
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を取得するコード Dim sSql As String
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 sSql As String
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を取得するコード(非接続型) Dim conn As New OracleConnection("User Id=Scott;Password=Tiger;Data Source=orcl")
‘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を返すパッケージの作成 CREATE OR REPLACE PACKAGE SCOTT.pkg_ref2 AS
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 sSql As String
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 conn As New OracleConnection("User Id=Scott;Password=Tiger;Data Source=orcl")
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 conn As New OracleConnection("User Id=Scott;Password=Tiger;Data Source=orcl")
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")
oo4oとODP.NETのトランザクション制御の違いについて見ていきましょう。まずは、oo4oでのトランザクション制御のコードについて説明します。
リスト.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の利用) Dim cnn As New OracleConnection
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コンポーネント単位でトランザクションの管理をおこないます。
ODP.NETでも同様にCOM+サービスを利用した自動トランザクションの制御は可能です。ODP.NETからCOM+を利用するには、Oracle Services for Microsoft Transaction Server(OraMTS)がインストールされ、適切に設定されている必要があります。COM+自体のトランザクション機能については、Microsoft社のCOM+に依存する内容であるため、Microsoft社のMSDNサイト、「.NETでCOM+ サービスを使用する」などを参照してください。
Visual Basic 6.0(以下、VB)からOracleデータベースへの接続ミドルウェアとして、oo4o以外にもADOを選択されている方も多いと思います。ここでは、VBでADOを使い Oracleデータベースにアクセスするアプリケーションを、どのように .NET 化すればよいか説明します。ADOとODP.NETで使用するオブジェクトは以下のようになります。
ADOでは、以下のコードのようにRecordSetを開いて、Movenextメソッドでシーケンシャルに読み込みながら処理を行うプログラミングスタイルが一般的だと思います。 リスト.29 ADOのRecordSetを利用したサンプルコード Do Until RecordSet.Eof
〜 データアクセス 〜 RecordSet.Movenext Loop 以上のコードですと、ループ処理の間はデータベースと接続された状態になっています。ODP.NETのOracleDataReaderは、ADOのRecordSetのReadOnly , FowardOnlyオプションで開いた状態に似ています。. NET環境からのデータアクセスは非接続型でのデータアクセスが主流になりますので、ADOからODP.NETへの移行も、oo4oからODP.NETの移行と同様に、非接続型でのデータアクセス手法を習得する必要があります。OracleDataAdapterを経由した、DataSetへのデータの格納と、DataSetからデータベースへのデータの書き戻しの概念を学ぶ必要があります。
しかし、既存のADOを利用して作成されたアプリケーションをODP.NETに変更するには、かなりのコードの修正が必要となります。とりあえず、最も簡単にADOを使用して作成されたアプリケーションを.NET化する方法として、Visual Studio .NETに付属している、アップグレードウィザードを使用する方法があります。アップグレードウィザードとは、Visual Basic 6.0 プロジェクトを Visual Basic .NET プロジェクトにアップグレードするツールになります。コマンドラインから、Vbupgrade.exe の引数にプロジェクトを指定することでアップグレードできますし、Visual Basic 6.0 のプロジェクトを Visual Studio .NET で開くと、自動的にウィザードが起動し、プロジェクトをアップグレードすることもできます。
実際に、アップグレードウィザードを使用してVisual Basic 6.0 プロジェクトを Visual Basic .NET プロジェクトに変換してみましょう。まずは、Visual Basic 6.0で作成された移行元のアプリケーションを作成します。Oracleデータベースにアクセスし、Visual Besic 6.0 の DataGrid コントロールにemp表の内容を表示するアプリケーションのコードは以下のようになります。 リスト.30 アップグレードウィザードを使用して、.NET化したコード Dim conn As ADODB.Connection
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 conn As ADODB.Connection
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へ手動でコードを変更したサンプル Dim conn As New OracleConnection( _
"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コントロールでも仕様は異なりますのでご注意ください。 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||