2

请您耐心看一下我将在下面编写的代码。我有两种方法:

     public void AddInParameters(string parameterName, OracleDbType dbtype,
                                                                 object value)
    {
        OracleParameter myparameter = new OracleParameter();
        myparameter.ParameterName = parameterName;
        myparameter.OracleDbType = dbtype;
        myparameter.Value = value;
        myparameter.Direction = ParameterDirection.Input;
        this._parameters.Add(myparameter);
    }

    public void AddOutParameter(string parameterName, OracleDbType dbType)
    {
        OracleParameter myparameter = new OracleParameter();
        myparameter.ParameterName = parameterName;
        myparameter.OracleDbType = dbType;
        myparameter.Direction = ParameterDirection.Output;
        this._parameters.Add(myparameter);
    }

私有字段_parameters 是List 类型。如您所见,这些方法分别创建 Input 和 Output 参数并将它们添加到 _parameters 列表中。然后我有以下方法,它将采用 OracleCommand 并将列表中的所有参数添加到其中:

     private void ProcessParameters(OracleCommand command)
    {
        foreach (OracleParameter myparameter in this._parameters)
        {
            command.Parameters.Add(myparameter);
        }
    }

这是我返回 OracleDataReader 的最终方法:

   public OracleDataReader ExecuteReader(string commandText, CommandType commandType)
    {
        OracleDataReader returnValue = null;
        OracleCommand myCommand = this.CreateCommand(commandText, commandType);
        this.ProcessParameters(myCommand);
        try
        {

            myCommand.Connection.Open();
            returnValue = myCommand.ExecuteReader(CommandBehavior.CloseConnection);
        }
        catch (Exception ex)
        {

            throw new DatabaseException(ex.Message);
        }


        return returnValue;

    }

所有这些方法都在数据访问层类库中。在我想调用 ExcuteReader 方法的类中,我按顺序执行以下操作:

  1. 我首先使用 AddInParameters 和 AddOutparameters 添加参数
  2. 然后我调用 ExecuteReader 方法。

但我有时会得到“错误数量或类型的参数”Oracle 异常。如果我拒绝使用这些方法并继续使用标准方式(创建连接,然后是命令,然后逐个添加参数,打开连接并最后调用 OracleCommand.ExecuteReader 方法),我不会收到该错误。奇怪的是我在我的应用程序入口处使用了这些方法,但在那里我从来没有遇到任何异常。我在执行 ExecuteReader 方法之前设置了一个断点来检查参数列表,一切似乎都很好,我的意思是所有参数都设置正确。你能告诉我我在这里缺少什么吗?

PS 我使用 .NET 的 Oracle 数据提供程序(Oracle.Data.Access.dll)。

4

2 回答 2

5

你试过用OracleCommand.BindByName = true吗?

于 2012-04-13T06:13:30.900 回答
3

花了我 1.5 天的时间找到解决问题的方法真的感觉很好。正如我已经说过的,Oracle 确实令人头疼。这就像一个“我不要这个,我不要那个,我要这样”的女孩。这么多细节,这么多需要考虑的事情。那些为甲骨文疯狂的人说,这就是甲骨文强大的原因。

经过长时间的战斗和绝望的搜索,@Dummy01 建议我设置 OracleCommand.BindByName=true。我实际上并没有立即尝试。我在 ODP.NET 文档中查找了该属性并查看了我发现的内容:

如果 OracleCommand BindByName 属性设置为 false(默认),则 ODP.NET 假定参数已根据其位置进行绑定,并且所有参数均已按正确顺序指定。

所以这意味着,如果在存储过程中参数的顺序是 p1、p2、p3,则必须以相同的顺序将这些参数添加到 OracleCommand.Parameters。否则会发生两件坏事:

  1. 更好的情况是你得到例外。假设您按 p1、p3、p2 的顺序传递它们,并且 p2 是 number 类型,而 p3 是 refcursor。数据库中的存储过程期望第二个参数是一个数字,第三个参数是 refcursor。但是由于参数传递的顺序与原始顺序不同,类型将不兼容,因此会引发异常。如果这些类型不同,那么您很幸运。

  2. 第二种也是最坏的情况是 p2 和 p3 都是相同的数据类型。我相信你可以猜到会发生什么:是的,你会为参数输入错误的值,这将导致 99% 的结果与预期的不同。

    我希望任何处理 Oracle 存储过程的人都考虑到这一点,否则他们可能会失去工作。祝你好运

于 2012-04-13T06:57:13.357 回答