Ognacの雑感

木漏れ日々

目次

Blog 利用状況

書庫

ギャラリ

ORACLE の DataReaderとDataAdapterの挙動不一致

環境
     ORACLE 10gEx
     Vista Ultimate(x86) + vs2005(C#/VB) + VS2008も同様:
Data操作は単純なのが好きなので、ADO.NETでは、Adapterを使ってません。
DataTableの Loadメソッドに DataReaderが使えるので必要が無かったです。
更新も、自動生成されるSQLは使わずに、自前で生成するので、尚更、使うことがなく、スッキリ記述できてました。
                    OracleDataReader dr = cmd.ExecuteReader();
                    DataTable dt = new DataTable();
                    dt.Load(dr);
なのに...
 ROLLUP 関数を使うことになって、次のSQL文を発行したところ
   select  A_id , B_id , sum(gaku)  from  Uriage  group by  ROLLUP(A_id , b_id)

【制約を有効にできませんでした。行に入力できるのは、Null 以外の値、一意な値、あるいは外部キーですが、この制約の違反が 1 つ以上の行で発生しています。】
のメッセージが出て落ちました。落ちた場所は、  dt.Load(dr);  の箇所です。
DB関係のメッセージは外れのことが多いので、悩みました。........皆目、見当が付かない。
 しかたがないのて、Adapter()を使ってみると
                    OracleDataAdapter oda = new OracleDataAdapter(cmd);
                    DataTable dt = new DataTable();
                    oda.Fill(dt);
なんの問題もなく、実行できます。うーん、なんでだろう。
Adapter.Fill も内部では、DataReader=>DataTable と似たような処理をしていると思うのだが、的外れな例外が理解できない。
 違う環境でテストしてないので、固有の現象か、一般的な現象かは不明ですが、 dt.Load(dr) と Adapter.fill() で、挙動が違うようなので、
Adapterを使わざるを得なくなりそう。なんかイヤだなぁ。

投稿日時 : 2008年6月13日 1:30

Feedback

# re: ORACLE の DataReaderとDataAdapterの挙動不一致 2008/06/13 14:07 Streetw☆

ステップ実行したら、dt.Load(dr)はAdapter.Fillをしてるみたいでした。
そうだとOracleDataAdapterでは何故大丈夫なのかな。。。

それは置いておいて;、
項目としてはNOT NULLなのに、ROLLUPの結果、
その項目がNULLになるのが原因かなって思って試したんですが、
私のとこではエラーにならなかったです。
(オラクルのバージョン違うけど、環境は書きません。。)

ROLLUPで指定する項目がcharの場合は、
DataTableに入ったときはNULLじゃなくなってました。
それで、数値項目にしてみたら、
OCI-22060: 引数[2]が無効か、または未初期化数値です。
というエラーが出ました。。。
やっぱりバージョン違うとダメですね。。。

少しコードを追加した下のコードで、何か原因わかりませんか~?

OracleDataReader dr = cmd.ExecuteReader();
DataTable dt = new DataTable();
DataSet ds = new DataSet();
ds.Tables.Add(dt);
ds.EnforceConstraints = false;
dt.Load(dr);
try
{
 ds.EnforceConstraints = true;
}
catch
{
 DataRow[] rows = dt.GetErrors();
 MessageBox.Show(rows.Length.ToString());
}

あ、もしかして、次のSQL文だと正常に処理されたりしませんか?

select nvl(A_id, A_id) as A_id, nvl(B_id, B_id) as B_id, sum(gaku)
from Uriage
group by ROLLUP(A_id, B_id)

# re: ORACLE の DataReaderとDataAdapterの挙動不一致 2008/06/13 14:09 Streetw☆

>ROLLUPで指定する項目がcharの場合は、
>・・・
>やっぱりバージョン違うとダメですね。。。

ここ、意味不明な文になってますorz
無視してください~

# re: ORACLE の DataReaderとDataAdapterの挙動不一致 2008/06/13 17:05 ognac

Streetw☆ さん。ありがとうごさいます。救世主に思える。

なんとなんと!!

>DataRow[] rows = dt.GetErrors();
>MessageBox.Show(rows.Length.ToString());

該当は 14で戻ってきますね。
各々のメッセージは
RowError: "Column 'JOB_ID' で DBNull.Value を使用できません。"

となります。



>select nvl(A_id, A_id) as A_id, nvl(B_id, B_id) as B_id, sum(gaku)
>from Uriage
>group by ROLLUP(A_id, B_id)


通ります。落ちない!!

???? 何か心当たりがあるのですか?

# re: ORACLE の DataReaderとDataAdapterの挙動不一致 2008/06/13 18:28 Streetw☆

>???? 何か心当たりがあるのですか?

いえ、勘が当たりました!w

>項目としてはNOT NULLなのに、ROLLUPの結果、
>その項目がNULLになるのが原因かなっ

が原因だと思います。

データベースでは「JOB_ID」をNOT NULLにされてると思いますが、
そうするとdt.Load(dr)のときに
dt.Columns["JOB_ID"].AllowDBNull
にfalseが設定されます。
それなのに実際はそこにROLLUPの結果のNULLの値が来るから
エラーになっちゃうと。

そこで、オラクルの関数とかの何かを使って、
項目値そのままじゃないように見せかけることで、
値にNULLが含まれると解釈されるように(AllowDBNullがtrueになるように)
どこかの処理を騙してみました。
騙したのはオラクルクライアントなのかSystem.Data.OracleClientなのか
わかってませんけど;

でも、OracleDataAdapterだと大丈夫な理由はやっぱりわかりません。。

# re: ORACLE の DataReaderとDataAdapterの挙動不一致 2008/06/13 20:34 ognac

>勘が当たりました!
鋭い勘ですね。
not null だからといって、制約を加えると、不味い気がします。
今回のように Rollup の結果如何ではNULLがあり得る訳で..
となると、dt.load(datareader)は使えないことになる....ちと辛いです。wwwww
DataAdapterの開発者はそれに気付いて、修正していたりして.....わかんないですね。

# re: ORACLE の DataReaderとDataAdapterの挙動不一致 2008/12/03 13:39 通りすがり

DataAdapterは制約関連をDataTableに組み込むか、組み込まないかをメソッドによって切り分けることが出来ます。
DataAdapter.Fillでは制約関連は取り込まれません。
DataAdapter.FillSchemaを使用することで制約もDataTableに設定されます。

おそらく、dt.Load(dr)は制約までも取り込んでしまうからなのではないでしょうか。

#と、通りすがり

# re: ORACLE の DataReaderとDataAdapterの挙動不一致 2008/12/03 22:03 Ognac

>dt.Load(dr)は制約までも取り込んでしまうからなのではないでしょうか
説明は付きますね。このあたりの資料が纏まってれば良いのですがねぇ。

# DataTableのLoad メソッド 2008/12/08 1:45 やじゅ@アプリケーション・ラボ わんくま支局

DataTableのLoad メソッド

# dKdCwuGDVMhuwP 2011/12/26 23:43 http://www.discreetpharmacist.com/ger/index.asp

Sent the first post, but it wasn`t published. I am writing the second. It's me, the African tourist.

# TZMcZrqvPqtfOodtMO 2011/12/27 0:26 http://www.discreetpharmacist.com/ger/index.asp

Very amusing thoughts, well told, everything is in its place:D

# gUPbZGajTX 2011/12/27 6:39 http://www.instawares.com/

Comrade kill yourself.

# JDbIGCecmLSdlnWYaKY 2011/12/27 19:55 http://www.instawares.com/

52. "The road will be overcome by that person, who goes." I wish you never stopped and be creative - forever..!

# UARVdFuGncaIgNBfti 2012/01/07 3:16 http://www.luckyvitamin.com/c-1181-arthritic-condi

A unique note..!

タイトル
名前
Url
コメント