0
Framework Version: v4.0.30319 
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AccessViolationException
Stack:
  at Oracle.DataAccess.Client.OracleParameter.SetStatus(Int32)
  at Oracle.DataAccess.Client.OracleParameter.PreBind(Oracle.DataAccess.Client.OracleConnection, IntPtr, Int32, Boolean)
  at Oracle.DataAccess.Client.OracleCommand.ExecuteNonQuery()

アプリケーションがこの例外でクラッシュします。context is: 2 つのパラメーターを受け入れるストアド プロシージャを実行しようとしています。コマンド テキストのパラメーターに名前バインディングを使用しています。

例:

OraCommand.CommandText = "begin LOAD_UTILS.TRUNCATE_TABLE(:a1,:a2); end;"
OraCommand.Parameters.Add(New OracleParameter("a1", OracleDbType.Varchar2, 1000))
OraCommand.Parameters(0).Direction = ParameterDirection.Input
OraCommand.Parameters(0).Value = params(2)
OraCommand.Parameters.Add(New OracleParameter("a2", OracleDbType.Varchar2, 1000))
OraCommand.Parameters(1).Direction = ParameterDirection.Input
OraCommand.Parameters(1).Value = params(3)

私が観察した奇妙な点は、エラーが発生した場合に備えて、特定の回数の再試行のためにこれらのステートメントを for ループで実行することです。OraCommand はインスタンス変数であるため、パラメーター コレクションはクリアされません。

反復 1 では、パラメータ a1、a2 が追加され
ます 反復 2 では、最初の 2 つのパラメータがすでに存在し、ここでも a1 と a2 という名前のパラメータを追加しています。...

すべての反復の開始時にパラメーター コレクションをクリアすると、問題が発生しませんが、ここで問題を引き起こしている理論を​​思い付くことができません。何か考えはありますか?

4

2 に答える 2

1

あなたはODP.Netを使用しています.Net C#APIは、OCI(Oracle Callインターフェース)と通信するCでサービスレイヤーを公開するための単なるラッパーであり、ほとんどの場合、アクセス違反の例外はサービスレイヤーまたはOCIから発生しますマネージ コード (.Net C#) にアクセス違反 (AV) を含めることは現実的ではないため、CLR はそれを許可しません。問題をデバッグするより簡単な方法は、Windbg を使用してシンボルをロードすることです。これにより、問題の原因となっている正確なメソッド (アンマネージ コード) が示されます。 ODP.Net 開発者が回避策と修正を提供できる Oracle Technet にコードの問題を投稿することもできます。ただし、その前に、私の見解では、コードに特定の問題があります。

ループでは、次の行は毎回新しいパラメーター a1 と a2 を追加します

OraCommand.Parameters.Add(New OracleParameter("a1", OracleDbType.Varchar2, 1000))
OraCommand.Parameters.Add(New OracleParameter("a2", OracleDbType.Varchar2, 1000))

新しいパラメータを作成した後でのみ、インデックス 0 と 1 で値と方向を設定しているため、発生している動作は予想通りです。これは毎回同じであり、反復ごとに 2 つの新しいパラメータを OracleCommand オブジェクトに追加することになります。あなたがしていることは間違っているので、内部構造を台無しにしているどこか。正しい方法は、ループ内の次のコードです。

OracleParameter A1 = OracleParameter("a1", OracleDbType.Varchar2, 1000)
A1.Direction = ParameterDirection.Input
A1.Value = params[2]
OracleCommand.Parameters[0] = A1;

OracleParameter A2 = OracleParameter("a2", OracleDbType.Varchar2, 1000)
A1.Direction = ParameterDirection.Input
A1.Value = params[3]
OracleCommand.Parameters[1] = A2;

実際、コードのもう 1 つの奇妙な点は、次のコードを使用して配列のようなコレクションにアクセスすることです。

OraCommand.Parameters(0).Value = params(2)

これは C# では不可能です。角かっこ [] を使用する必要があります。私の意見では、VB.Net を使用している必要がありnewます。正しくないため、NewC#にはありません。

于 2014-12-17T05:32:15.000 に答える
0

@Mrinal Kamboj そうです、コードは VB.NET にあります。ExecuteNonQuery を実行しようとすると、例外がスローされました。私はWinDbgを試しましたが、これが得られるものです: ここに画像の説明を入力

于 2014-12-17T15:28:05.107 に答える