39

これは絶対的な遠吠えです。私は自分の目を信じることができず、これが C# の本物のバグであるとしたら、私より前に誰もこれを発見しなかったとは信じられません。この質問には、「DOH!」と言うことが含まれると確信しています。手のひらで私の頭を強くたたきました - とにかく、ここに行きます...

Test_1テストのために、次のスクリプトを使用してテーブルを作成しました。

CREATE TABLE TEST_1 (
  COLUMN1 NUMBER(12) NOT NULL,
  COLUMN2 VARCHAR2(20),
  COLUMN3 NUMBER(12))
TABLESPACE USERS
STORAGE (
  INITIAL 64K
  MAXEXTENTS UNLIMITED
)
LOGGING;

ここで、次のコードを実行します。

var conn = new OracleConnection("connectionblahblah");
conn.Open();
var cmd = conn.CreateCommand();
cmd.CommandText = 
  "insert into Test_1(Column1, Column2, Column3) " +
  "values(:Column1, :Column2, :Column3)";
var p = cmd.Parameters;
p.Add("Column1", 1);
p.Add("Column3", null);
p.Add("Column2", "record 1");
cmd.ExecuteNonQuery();

うわあ!ORA-01722 エラー - 「無効な番号」が表示されます。しかし、何が問題なのですか? Column1数値であり、値が 1 であるため、問題ありません。Column2は文字列でありColumn3、null 可能な列であるため、問題は発生しません...

さて、これについて座ってください...ここでの問題は、Column3Column2が に追加される順序で転置されることOracleParameterCollectionです。それらを切り替えて、早速!できます!

もちろん、これは次の明らかな実験につながります...次のようにパラメーターを追加するためにコードのブロックを変更しましょう。

p.Add("Foo", 1);
p.Add("Bar", "record 1");
p.Add("hahahahahahaha", null);

うまくいくと思いますか?何を推測しますか-それはあります!

私は完全に唖然としてここに座っています。私は自分が見ているものを信じることができず、同様に、私の前に誰もこの振る舞いを発見していないとも信じられません (Google の適切な使い方を知らない限り)。

これは単なる煩わしさではなく、非常に危険です。同じデータ型の 2 つの列を転置したらどうなるでしょうか? エラーが発生することさえありませんでした.間違ったデータを間違った列に挿入しただけで、賢明ではありませんでした.

パラメータを間違った順序で追加しないように注意する以外に、回避策のアイデアはありますか?

4

3 に答える 3

49

これはバグではありませんが、Oracle ODP.Net のドキュメントに明示的に記載されています。OracleCommand クラスでは、パラメータはデフォルトで位置によってバインドされます。名前でバインドする場合は、プロパティをcmd.BindByName = true;明示的に設定します。

Oracle ドキュメントへの参照。 http://download.oracle.com/docs/cd/E11882_01/win.112/e12249/OracleCommandClass.htm#i997666

于 2010-10-06T22:26:45.193 に答える
5

column2 の前に column3 が追加されているのはタイプミスですか?

コロン構文はバインド変数を意味するため、名前は PLSQL の BIND 変数には関係なく、送信順に入力されます。これは、列 2 の値を「レコード 1」として設定しようとしていることを意味します。これは、無効な数値エラーを説明します...

あなたは現在持っています:

p.Add("Column1", 1);
p.Add("Column3", null);
p.Add("Column2", "record 1");

...この変更で問題が解決するかどうかを確認してください:

p.Add("Column1", 1);
p.Add("Column2", "record 1");
p.Add("Column3", null);

名前付きパラメータを機能させるには?

名前付きパラメーターを機能させる方法については、C# の経験が豊富な人に任せる必要があります。しかし、コロンが Oracle BIND 変数として解釈されているように見えることを確認できてよかったです。

于 2010-10-06T21:07:07.913 に答える
0
p.Add(":Column1", 1);
p.Add(":Column2", "record 1");
p.Add(":Column3", null);

//NOTE を追加しました: Oracle データ クライアントによって認識されるパラメータ名に

于 2013-06-06T15:36:09.453 に答える