2

以下に書くコードを確認するまで、しばらくお待ちください。私には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 型です。ご覧のとおり、これらのメソッドはそれぞれ入力パラメーターと出力パラメーターを作成し、それらを _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 例外が発生することがあります。これらのメソッドの使用を拒否した場合、標準的な方法 (接続を作成し、次にコマンドを作成し、パラメータを 1 つずつ追加し、接続を開き、最後に 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 に追加する必要があることを意味します。そうしないと、次の 2 つの問題が発生する可能性があります。

  1. より良いケースは、例外が発生することです。それらを p1、p3、p2 の順に渡し、p2 が number 型で、p3 が refcursor であるとします。データベースのストアド プロシージャは、2 番目のパラメータが数値で、3 番目のパラメータが refcursor であることを想定しています。ただし、パラメーターを渡す順序が元の順序と異なるため、型に互換性がなくなり、例外がスローされます。それらのタイプが異なる場合はラッキーです。

  2. 2 番目の最悪のケースは、p2 と p3 の両方が同じデータ型である場合です。何が起こるかは推測できると思います:はい、パラメータに間違った値を入力すると、99% の確率で予想とは異なる結果が生じます。

    Oracle ストアド プロシージャを扱う人は、この点を考慮してください。そうしないと、職を失う可能性があります。幸運を

于 2012-04-13T06:57:13.357 に答える