7.Oracle編
Oracle用データプロバイダ「System.Data.OracleClient」を使用したDBアクセスについて解説を行います。OracleについてはWikipediaなどを参照してください。
「System.Data.OracleClient」は「OCI(Oracle call-level interface)」を必要とします。Oracle 8i、9i、10g、11g に対応しています。
「OCI(Oracle call-level interface)」は、Oracle DBのデータを操作するために使用するCライブラリ関数です。詳細についてはOracle Technology Networkを参照して下さい。
セットアップ
ホストOS側で動作確認用Oracle DBを作成します。ゲストOS側でOracle用データプロバイダ「System.Data.OracleClient」の準備を行います。
「Oracle Database 10g Express Edition」はOracle Technology NetworkからWindows用のリンクを選択し、「Oracle Database 10g Express Edition (Universal)」(OracleXEUniv.exe)をダウンロードし、インストールを行います。本稿ではインストール自体の解説は割愛します。
「System.Data.OracleClient」は、Mono 1.9.1のソース(mono-1.9.1.tar.bz2)をNovell社のサイトからダウンロードし、その中に含まれる「System.Data.OracleClient」のソースコードを修正し、ビルドします。詳細についてはデータプロバイダで解説します。
「OCI(Oracle call-level interface)」については、Oracle Technology NetworkからLinux用のリンクを選択し、「Oracle Database 10g Express Client」(oracle-xe-client-10.2.0.1-1.0.i386.rpm)をダウンロードして、インストールすることで対応します。
Oracle DB
動作確認用DB(TESTDATA.PRODUCTS)を作成します。sqlplusユーティリティを使用したDB操作を行います。
テーブル作成用SQLファイルの準備
「D:\Dev\Oracle\sql」(任意)に以下のテーブル作成用SQLファイルを用意します。
--sqlplus testdata/password @Products.sql
--
-- Products テーブル削除
--DROP TABLE Products;
-- Products テーブル作成
CREATE TABLE Products (
ProductID NUMBER(5) NOT NULL,
ProductName NVARCHAR2(25) NOT NULL,
Price NUMBER(7, 2),
ProductDescription NVARCHAR2(128) NULL);
-- Products テーブル プライマリキー作成
ALTER TABLE Products ADD CONSTRAINT Products_PK PRIMARY KEY (ProductID);
-- INSERT 実行
INSERT INTO Products (ProductID, ProductName, Price, ProductDescription)
VALUES (0, 'Oracle', NULL, 'Oracle Database 10g Express Edition');
-- INSERT 実行
INSERT INTO Products (ProductID, ProductName, Price, ProductDescription)
VALUES (1, 'Clamp', 12.48, 'Workbench clamp');
-- INSERT 実行 カラムの順番を変えたパターン
INSERT INTO Products (ProductName, ProductID, Price, ProductDescription)
VALUES ('Screwdriver', 50, 3.17, 'Flat head');
-- INSERT 実行 カラムリスト指定なし、入力値リストはカラム順パターン
INSERT INTO Products
VALUES (75, 'Tire Bar', NULL, 'Tool for changing tires.');
-- INSERT 実行 ProductDescription カラムの指定なしパターン
INSERT INTO Products (ProductID, ProductName, Price)
VALUES (3000, '3mm Bracket', .52);
-- UPDATE 実行
UPDATE Products
SET ProductName = 'Flat Head Screwdriver'
WHERE ProductID = 50;
-- SELECT 実行 確認用
SELECT *
FROM Products;
-- 終了
EXIT
Oracleデータベースの起動
Oracleデータベースを起動するには、[スタート]-[すべてのプログラム]-[Oracle Database 10g Express Edition]-[データベースの起動](停止は[データベースの停止])を選択します。
ユーザ作成
> sqlplus system/password SQL> create user testdata 2 identified by password 3 default tablespace users 4 temporary tablespace temp;
権限の付与
ユーザーに権限(例:ロール(CONNECT,RESOURCE))の付与を行います。
> sqlplus system/password SQL> grant connect,resource to testdata;
テーブル作成
> D: > cd Dev\Oracle\sql > sqlplus testdata/password @Products.sql
データプロバイダ
Mono 1.9.1から提供されている「mono-data-oracle」パッケージに含まれる「System.Data.OracleClient」にはデータプロバイダファクトリ対応クラス「OracleClientFactory」が実装されていません。「machine.config(2.0 profile)」には標準で「System.Data.OracleClient」のデータプロバイダファクトリ情報が登録されているので、肩透かしをくらったような感じがしましたが、とりあえず対応方法があったので、深く考えないことにします。
「System.Data.OracleClient」への修正
「System.Data.OracleClient」のソースコードの修正、ビルドについて 、Novell's Bugzillaに、関連すると思われる情報があったので参考にしました(Bug #365911)。
修正内容については、Mono Anonymous SVN Repositoriesに存在するbranchesおよびtrunk内の「System.Data.OracleClient」配下のソース資源を参考にしました(注:実際に作業を行ったのは、2008年8月上旬で、その時点でのソース資源を参考にしました)。
ダウンロードしたMono 1.9.1ソース資源内の「System.Data.OracleClient」配下のソース資源に、「OracleClientFactory.cs」の追加、以下の既存資源への修正対応を行います。
「~/tmp」 配下に「mono-1.9.1.tar.bz2」を展開する場合: > cd ~/tmp > tar xjvf mono-1.9.1.tar.bz2 ~/tmp/mono-1.9.1/mcs/class/System.Data.OracleClient 配下 System.Data.OracleClient.dll.sources:修正 System.Data.OracleClient/OracleClientFactory.cs:追加 System.Data.OracleClient/OracleConnection.cs:修正 System.Data.OracleClient/OracleCommand.cs:修正 System.Data.OracleClient/OracleDataReader.cs:修正 System.Data.OracleClient/OracleParameter.cs:修正 System.Data.OracleClient/OracleParameterCollection.cs:修正
440行目
#if NET_2_0
[MonoTODO]
protected override Common.DbTransaction BeginDbTransaction (IsolationLevel level)
{
return null;
}
[MonoTODO]
protected override Common.DbCommand CreateDbCommand ()
{
return null;
}
#endif
変更
#if NET_2_0
[MonoTODO]
protected override Common.DbTransaction BeginDbTransaction (IsolationLevel level)
{
//return null;
return (Common.DbTransaction)BeginTransaction (level);
}
[MonoTODO]
protected override Common.DbCommand CreateDbCommand ()
{
//return null;
return CreateCommand ();
}
#endif
また、SQL文字列内にパラメータを使用して、パラメータに日本語のようなマルチバイト文字を含む文字列をバインドした場合、以下の例外が発生するので、
ORA-01480: STRバインド値に終了のNULLがありません。
原因箇所のある「OracleParameter.cs」に以下の修正を行う必要があります。
523行目 bindSize = svalue.Length; 変更 bindSize = bytes.Length;
修正対応後、Mono 1.9.1自体のビルドを行います。
> cd ~/tmp/mono-1.9.1 > ./configure > make PROFILE=net_2_0
ビルド後、「System.Data.OracleClient」をGACへ登録(もしくはMONO_PATHによる配置)を行います。
> cd ~/tmp/mono-1.9.1/mcs/class/lib/net_2_0 > su # gacutil -i System.Data.OracleClient.dll -package 2.0 Package exported to: /usr/lib/mono/2.0/System.Data.OracleClient.dll -> ../gac/System.Data.OracleClient/2.0.0.0__b77a5c561934e089/System.Data.OracleClient.dll Installed System.Data.OracleClient.dll into the gac (/usr/lib/mono/gac)
また、「Oracle Database 10g Express Client」インストール後、環境変数設定を行う必要があります。以下の設定を「~/.profile」等に追加します。
#ADD for Setting the Oracle Database XE Client Environment Variables . /usr/lib/oracle/xe/app/oracle/product/10.2.0/client/bin/oracle_env.sh
なお、今回使用した「System.Data.OracleClient」の修正済み修正対象ファイル、アセンブリ「System.Data.OracleClient.dll」をサンプルとして本稿に添付しました。
