我试图调用一个返回类型为number的Oracle函数。我使用OleDB从C#调用,我理解Oracle中类型编号的映射是小数。每当我打电话给我时,我都会回来。
using (OleDbCommand _cmdDueAtDock = new OleDbCommand()) {
_cmdDueAtDock.Connection = connection;
_cmdDueAtDock.CommandType = CommandType.StoredProcedure;
_cmdDueAtDock.CommandText = "IFSAPP.PURCHASE_ORDER_LINE_API.GET_DUE_AT_DOCK";
_cmdDueAtDock.Parameters.Add(new OleDbParameter() {
ParameterName = "rv_",
OleDbType = OleDbType.Decimal,
Direction = ParameterDirection.ReturnValue
});
_cmdDueAtDock.Parameters.Add(new OleDbParameter() {
ParameterName = "order_no_",
OleDbType = OleDbType.VarChar,
Size = 50,
Direction = ParameterDirection.Input,
Value = _order_line.ORDER_NO
});
_cmdDueAtDock.Parameters.Add(new OleDbParameter() {
ParameterName = "line_no_",
OleDbType = OleDbType.VarChar,
Size = 50,
Direction = ParameterDirection.Input,
Value = _order_line.LINE_NO
});
_cmdDueAtDock.Parameters.Add(new OleDbParameter() {
ParameterName = "release_no_",
OleDbType = OleDbType.VarChar,
Size = 50,
Direction = ParameterDirection.Input,
Value = _order_line.RELEASE_NO
});
try {
_cmdDueAtDock.ExecuteNonQuery();
dueAtDock = Convert.ToDecimal(_cmdDueAtDock.Parameters["rv_"].Value);
} catch (Exception ex) {
dueAtDock = 0;
}
}
我使用Oracle client 11.2.0
,oracle数据库版本为10.2.0.4.0
。
我已经读过有关11.1客户端有问题的内容,我实际上能够通过select to_char(function) from dual
对11.1客户端的行为进行总结 - 我得到的结果不是to_char
而是0
与to_char
。将我的客户端升级到11.2可以在本地解决此问题。
答案 0 :(得分:1)
非常感谢您的回复,但这取决于数据库事务和代码执行的顺序 - 在此之前有一段代码正在执行影响函数结果的内容。
希望我的遗失能够帮助其他正在摸不着头脑的人!
的Dom
答案 1 :(得分:0)
我的猜测是值始终为0,因为catch块总是被触发。我看到一个明显的罪魁祸首,另一个可能。我假设您的存储过程看起来像这样:
create or replace procedure GET_DUE_AT_DOCK(
order_no_ in varchar2,
line_no_ in varchar2,
release_no_ in varchar2,
rv_ out number
) as
BEGIN
rv_ := 999;
END;
我认为您的ParameterDirection
财产需要Output
而不是ReturnValue
。我可能错了,但我认为ReturnValue
与普通的SQL命令一起使用,你有一个RETURNING
子句,例如:
insert into foo (name, birthday)
values (:NAME, :BIRTHDAY)
returning unique_id into :ID;
我可能错了,但这就是我的想法。
其次,对于存储过程,我认为参数的声明很重要,需要与过程中的实际参数保持一致。如果我上面的例子在概念上是正确的,那么你需要按照确切的顺序(order_no,line_no,release_no,rv)放置参数。如果没有真正看到您的存储过程,很难说 - 您实际上可能是正确的。
所以,假设SP看起来像我的例子,这应该这样做:
_cmdDueAtDock.Parameters.Add(new OleDbParameter() {
ParameterName = "order_no_", OleDbType = OleDbType.VarChar,
Direction = ParameterDirection.Input, Value = _order_line.ORDER_NO });
_cmdDueAtDock.Parameters.Add(new OleDbParameter() {
ParameterName = "line_no_", OleDbType = OleDbType.VarChar,
Direction = ParameterDirection.Input, Value = _order_line.LINE_NO });
_cmdDueAtDock.Parameters.Add(new OleDbParameter() {
ParameterName = "release_no_", OleDbType = OleDbType.VarChar,
Direction = ParameterDirection.Input, Value = _order_line.RELEASE_NO });
_cmdDueAtDock.Parameters.Add(new OleDbParameter() {
ParameterName = "rv_", OleDbType = OleDbType.Decimal,
Direction = ParameterDirection.Output }); /// <- change is here
try
{
_cmdDueAtDock.ExecuteNonQuery();
decimal dueAtDock = Convert.ToDecimal(_cmdDueAtDock.Parameters[3].Value);
}
catch (Exception ex)
{
decimal dueAtDock = 0;
}