2 つの ODT をくらべてみる (自動生成コード編)
検証環境 自作マシン(Core2QuadQ9400 2.66GHz/4GB)
Windows7 Ultimate(6.1.7600) – x86
VisualStudio2008Pro(VB) 9.0.30729.1SP/.NET Framework 3.5SP1
Oracle Database 11g 11.1.0.6.0
Oracle Developer Tools for Visual Studio 11.1.0.7.20Windows XP Professional SP3
VisualStudio2008Pro(VB) 9.0.21022.8/.NET Framework 3.5SP1
Oracle Developer Tools for Visual Studio.NET 11.1.0.6.20
先日、猿頁 » Blog Archive » Oracle Developer Tools for Visual Studio 11.1.0.7.20 で 今年 9 月あたりに新しく提供された、Oracle Developer Tools for Visual Studio (以下 ODT) 11.1.0.7.20 を軽くイジってみたわけですが。
なんだかあちこち、データセットデザイナの動作が変わっているような気がします。
でも直接比較したわけではないので、私の記憶違いという気もしないでもありません。
つことで、まずは 11.1.0.6.21 (旧版)と 11.1.0.7.20 (新版)で自動生成されたデータセットクラスのソースコードを少し見比べてみることにしました。
このへん、あまり情報が提供されていないんですよね。くすん。
当たり前ですが、2 つのリビジョンの ODT を、1 つの開発環境に混在させることはできません。
ので今回は、むりやり開発環境を 2 つ作ってみました。
ひとつは、先日から使用している Win7+VS2008SP1+ODT 11.1.0.7.20。
Oracle 11g サーバも、この環境に入っています。
もうひとつは、同じマシンに VirtualPC でWinXPを構築し、VS2008SP1+ODT.NET 11.1.0.6.20をインストール。
ゲスト XP から、ホスト Win7 の Oracle 11g サーバへアクセスできるようにしました。
もーこの環境作るのにざっと 3 週間かかりました。
VirtualPC for Windows7 を動かすために CPU を Core2Duo から Quad に差し替え、メモリも増設してスワップによる低速化を回避し、ODT 11.1.0.6.20 のインストールに難儀し、ゲスト→ホスト間の通信に難儀し。
実はホスト OS の IP アドレスを固定にできないため、起動するごとに ルータの DHCP から別番が振り当てられ、ゲスト OS 側で手動で再認識させなければならない状態だったりします。
固定 IP にすると、DNS サーバを認識しなくなるんですよね…それはそれで困っちゃうので。どうも IPv6 あたりが邪魔をしているようです。そのへんはまたいずれ。くそー。
さて、本論。まずは ODT 11.1.0.7.20 の環境で作業。
何もしない「空のプロジェクト」を作成します。
ちなみに、私の VS は「Visual Basic 開発設定」の設定で、さらに自分流に少々カスタマイズしてあります。他の開発設定を選択している環境とはあちこち表示が違います(たとえば上記「新しいプロジェクト」ダイアログの[プロジェクトの種類]ペインのツリー構造とか)ので、そのへんはつど読み変えてくださいよろしくお願いします。
で、ソリューションエクスプローラからデータセットを追加します。
データセットデザイナがドキュメントウィンドウペインに表示されたらデザイナウィンドウから TableAdapter 構成ウィザードを起動します。
デザイナウィンドウあたり(データセットファイルあたり)最初の TableAdapter の新規作成時には、TableAdapter 構成ウィザードは「データ接続の選択」から始まります。
あらかじめサーバーエクスプローラで使用する DB への接続を登録しておくと、この画面では[アプリケーションがデータベースへの接続に使用するデータ接続]のコンボボックスに選択肢として表示されますので、使いたい接続を選択するだけで済むので便利です(今回は「SALV.SALV」という接続を使います)。
「重要情報」(Oracle への接続では、通常パスワードのことを指します)もめんどくさいので、今回は[はい、重要情報を接続文字列に含めます。]を選択します。
次の「接続文字列をアプリケーション構成ファイルに保存する」では、初期値のまま[次の名前で接続を保存する]にチェック-[ConnectionString]とします。
次の「コマンドの種類を選択します」では、[SQL ステートメントを使用する]を選択します。
次の「SQL ステートメントの入力」から「クエリビルダ」ダイアログを表示させます。
「テーブルの追加」ダイアログも併せて表示されますので、今回は TBL_PARENT (SALV) テーブルを追加します。
クエリビルダのダイアグラムペイン (一番上の枠) に追加された TBL_PARENT テーブルの各フィールドにチェックをつけると、抽出条件ペイン (上から 2番目の枠) と SQL ペイン (3 番目の枠) にもシンクロしてそれぞれの様式で表示されます。
TableAdapter 構成ウィザードの次の画面「生成するメソッドの選択」も、初期値のままとします。
これでひととおりの構成ができました。
次、同じ作業を ODT 11.1.0.6.21 の環境でやってみます。
…あー、やっぱり。
ダイアグラムペインの TBL_PARENT テーブルに「ROWID」が表示されていません。これは 11.1.0.7.20 からの新機能?みたいですね。
とまあだいたいこんな感じで。
これで 11.1.0.7.20 製、11.1.0.6.21 製の 2 つのプロジェクトができました。どちらも実行できるわけではありませんが、IDE 内では データセットデザイナからちょろちょろと DB をいじることはできます。
この状態で、2 つのプロジェクトを丸ごと比較してみましょう。
突き合わせには、WinMerge (日本語版) を使ってみます。
.sln、.suo、.vbproj、.vbproj.user はソリューションやプロジェクトの情報ですので、今回は無視します。bin、My Project、obj フォルダもデータベースには直接関係ありません。
app.config には、
TableAdapter 構成ウィザードの最初で設定した「接続情報」が格納されています。
区別をつけるためにプロジェクト名を変えていますので名前空間も変わるため、ConnectionString の識別名の最初の方が異なっているというだけですね。
内容としては、同じ情報が同じ状態で生成されています。
DataSet1.xss には、
デザイナウィンドウの中の TBL_PARENT オブジェクトの表示座標情報が格納されています。
ぴったり同じ位置に生成されるわけではないので、まあズレていても当たり前ですね。
これもデータアクセスそのものには無関係です。
DataSet1.xsd は、3 か所異なる部分があります。
1 か所目は、app.config の接続情報を参照するところですね。
app.config の識別名がズレているので、当然参照の指定もズレます。
2 か所目は、Select 文が格納されている部分です。「ID」と「TBL_PARENT」それぞれの直前に、11.1.0.6.21 製にはなかった空白が 11.1.0.7.20 製では生成されています。
念のためにバイナリエディタで文字コードも確認しましたが、
ほんとにただの半角スペースですね。
空白の個数を変更した理由はよくわかりませんが、変わったからといって動作に影響があるわけではありませんので、気にする必要もありません。
3 か所目。
ここは、「 msprop:Generator_DataSetName="DataSet1"」と「msprop:Generator_UserDSName="DataSet1"」の記述順が逆になっているだけです。
.xsd ファイルは xml ですから基本的には記述順は関係なく、タグ等から情報の「役割」を判定して参照するような使われ方をしているはずです。何らかの参照時にシーケンシャルに読み込んでいるための対応(バグフィックス)の可能性もなくはありませんが、意味的にもキーワード的にも等しいので、ここも気にしないこととします。
DataSet1.Designer.vb は、けっこう大量の相違点があります。
しょっぱなのランタイムバージョンの違いは、.NET CLR のバージョンのようです。
末尾のずれは、Windows7 と XP で提供されている .NET ランタイムがびみょーに異なるか、アップデート状態が異なるかのどちらかの理由のように思いますので、ここでは気にしないこととします。
InitAdapter メソッド内の相違点は、すべての「param.OracleDbType」が「param.OracleDbTypeEx」に置き換わっているだけですね。
param は Global.Oracle.DataAccess.Client.OracleParameter クラスのインスタンスを格納する変数ですので、11.1.0.6.21 と 11.1.0.7.20 では OracleParameter の扱い方が違うということになります。
11.1.0.7.20 環境の OracleParameter の構成を見ると、OracleDbType と OracleDbTypeEx 両方のプロパティが定義されています。
でもってこの 2 つのプロパティは、ともに Oracle.DataAccess.Client.OracleDbType の型となっています。
一方 11.1.0.6.21 では、OracleDbType だけが定義されています。OracleDbTypeEx は存在しません。
最近の ODP.NET の開発者ガイドでは、クラスのリファレンスが日本語化されていません。
近いところでは、10.2.0.2の開発者ガイドで OracleDbType を
OracleDbType
OracleParameterオブジェクトが配列バインドまたはPL/SQL連想配列バインドの実行に使用される場合、OracleDbTypeは、配列内の各要素のデータ型になります。
OracleDbTypeプロパティとDbTypeプロパティは、リンクされています。したがって、OracleDbTypeプロパティを設定すると、DbTypeプロパティが、サポートしているDbTypeに変更されます。
と説明しています。
一方 11.1.0.7.20 の Oracle® Data Provider for .NET Developer's Guide では
OracleDbType
Default = OracleDbType.Varchar2
If the OracleParameter object is used for Array Bind or PL/SQL Associative Array Bind execution, OracleDbType is the data type of each element in the array.
The OracleDbType property and DbType property are linked. Therefore, setting the OracleDbType property changes the DbType property to a supporting DbType.
と完全に対応する英文が記載されていますので、まあ 10.2.0.2 ~ 11.1.0.7.20 まで OracleDbType の機能には変化はないと思います。
で、その直後に
OracleDbTypeEx
This property is used by applications that need to bind a parameter value as an Oracle type, but need a .NET type back for output. This property should be used with an output or input/output parameter. For an input parameter, using OracleDbTypeEx has the same affect as using OracleDbType. The .NET type that is returned for the output is the .NET type that the Oracle type closely maps to.
とあり、どうも「戻り値を .NET の型として返す」ところで OracleDbType とは異なる、と説明されているように読めるんですが。
もひとつの情報として、Mark Williams さんの blog で、Oracle と .NET で型がぶつかるあたりのエントリが上がっています。
まだちゃんと読み込んでいないんですが、たぶん OracleDbTypeEx が提供された理由に言及されているんだと思われます。
でもまあこれらは内部的に処理される部分の記述で、直接こちらで記述したコードと関わるものではありませんので、まあいいかなーという気がします。
ちなみに、11.1.0.6.21 で作成したプロジェクトを 11.1.0.7.20 環境で読み込んで TableAdapter 構成ウィザードを走らせ直すと、OracleDbType の記述は OracleDbTypeEx に変更されました。
てことは、実行環境より開発環境の ODP.NET のリビジョンが上がるとエラーになる可能性があるってことですね。逆は吸収できる感じのようですが。
あと、InitConnection メソッドでは DataSet1.xsd と同様の、「ConnectionString の識別名の違い」と「SELECT 文のスペース数の違い」がありました。
以上から、とりあえず
- デザイナから自動作成される各データセットクラスのコードは、ほぼ同一。
- 11.1.0.6.21 で生成したコードは 11.1.0.7.20 で読み込み可能、変更可能。
- 一部 11.1.0.7.20 の追加機能が使われているので、古い実行環境ではたぶん動作しない。
というところが調査結果でしょうか。
自動生成コードについての確認は、私にとってはこれで十分です。
次回は、11.1.0.6.21 で気になっていた、SQL 文の生成機能の部分を確認してみたいと思っていますよー。






































前回のODT検証に引き続き、興味深く拝読させて頂きました。
OracleDbTypeとOracleDbTypeExの変更点は確かに気になりますね。
DACのHelperクラスを共通部品として製造したことがありますが、
ストアドのインターフェイスの型をOracleDbTypeのCase文で判別しているので、
既存の挙動と、型の解釈が異なる部分があるかもしれませんね。