OracleClient vs ODP.NET

Oracle用のプロバイダとしては、Microsoftが提供するOracleClientとOracleが提供するODP.NETがあります。当然、Oracleが出している方が高性能なんですが、以下のようなデメリットがあります。

  1. 標準では入っていないのでダウンロードする必要がある
  2. Visual Studio 2005のWizardに対応していない

このうち、後者がネックです。なんと言っても型付DataSetとTableAdapterが使えないのは痛すぎます。仕方ないのでOracleClientを使うことにしようかと思ったのですが、こっちはこっちで別の問題が発生しました。
トランザクション分離レベルをSerializableにすると、ダーティリード、反復不能読み取り 、ファントムリードのすべてに対し、安全です。たとえば、トランザクション中で件数を調べるをクエリーを発行し、その後、別トランザクションでデータの挿入&コミットがあったとしても、同じクエリーを発行すれば、同じ結果が戻るはずです。ということで実験君。

conn.Open();
using (OracleTransaction tx = conn.BeginTransaction(IsolationLevel.Serializable))
{
    cmd.Transaction = tx;
    cmd.CommandText = "SELECT COUNT(*) FROM USER";                    
    
    // count(*)で件数を取得
    object cnt = cmd.ExecuteScalar();
    
    // このタイミングでSQL*Plusからデータを削除
    
    // 分離レベルがSerializableなのでcntは同じ値が戻るはず
    // ODP.NETだと、同じ値(正しい)
    // System.Data.OracleClientだと削除後の数が戻る(Serializableの挙動ではない)
    cnt = cmd.ExecuteScalar();
    
    tx.Rollback();
}
conn.Close();
conn.Dispose();

OracleClientを使うと正しい結果になりません。もしかして?っと、

cmd.CommandText = "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE";
cmd.ExecuteNonQuery();

自分で分離レベルを変更してやると今度は正しい結果になりました。OracleClientのIsolationLevel.Serializableは無視されているみたいです。これって不具合じゃないのでしょうか?>OracleClient

こんな感じなのでOracleClientを使って大丈夫なのか不安になりました。