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是一个可以为空的列,所以不应该造成任何麻烦......

现在坐下来听这个...这里的问题是Column3并且Column2按照它们添加到OracleParameterCollection. 切换它们,然后!有用!

当然,这将引导我进行下一个明显的实验......让我们更改该代码块以添加参数,如下所示:

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

你认为这会奏效吗?好吧,猜猜看 - 它确实如此

我坐在这里完全惊呆了。我无法相信我所看到的,我同样无法相信在我之前没有人发现这种行为(除非我不知道如何正确使用 Google)。

这不仅仅是一个烦恼 - 它是非常危险的。如果我转置了相同数据类型的两列会发生什么?我什至不会出错——我只是将错误的数据插入到错误的列中,而且一点也不聪明。

有没有人有任何解决方法的想法 - 除了小心不要以错误的顺序添加参数?

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

这是您在第 2 列之前添加第 3 列的错字吗?

因为冒号语法表示绑定变量——名称与 PLSQL 中的 BIND 变量无关,它们按提交顺序填充。这意味着您将尝试将 column2 值设置为“记录 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);

//注意我已经添加:到oracle数据客户端识别的参数名称

于 2013-06-06T15:36:09.453 回答