5

次のコードを使用してSQL Developerから呼び出すと、完全に正常に機能するOracleのプロシージャがあります。

VARIABLE x REFCURSOR
exec MY_PROCEDURE('par1', 'par2', 'par3', 'par4' ,:x);
PRINT x;

.Net アプリから (ODP.NET を使用して) 呼び出そうとすると、次のエラーが発生します。

Oracle.DataAccess.Client.OracleException ORA-08103: object no longer exists

これは私がそれを呼び出すために使用するコードです:

OracleConnection con = new OracleConnection();
con.ConnectionString = dbConnectionString; //string with the connectio. It is fine because I can connect

OracleCommand cmd = new OracleCommand("MY_PROCEDURE", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = con;

cmd.Parameters.Add(new OracleParameter("par1", OracleDbType.Varchar2)).Value = var1;
cmd.Parameters.Add(new OracleParameter("par2", OracleDbType.Varchar2)).Value = var2;
cmd.Parameters.Add(new OracleParameter("par3", OracleDbType.Varchar2)).Value = var3;
cmd.Parameters.Add(new OracleParameter("par4", OracleDbType.Varchar2)).Value = var4;

OracleParameter ref_cursor = new OracleParameter();
ref_cursor.OracleDbType = OracleDbType.RefCursor;
ref_cursor.Direction = ParameterDirection.Output;
cmd.Parameters.Add(ref_cursor);

con.Open();

OracleDataReader dr = cmd.ExecuteReader();

while (dr.Read())
{  ...   }

cmd.ExecuteReader コマンドは実際には「動作」し、アプリケーション例外がスローされますが、オブジェクトdr.readをチェックすると、プロパティでエラーが表示されます。drhasRowsORA-08103: object no longer exists

何が間違っている可能性がありますか?詳細の 1 つは、(カーソルを返す) ほぼ同じロジックに従い、正常に動作する同様の手順があることです。

4

2 に答える 2

9

返されたカーソルのクエリには一時テーブルが含まれますか?ON COMMIT DELETE ROWSオプションを使用して一時テーブルを含むカーソルを返し、カーソルデータを取得する前にトランザクションをコミットすると、足を踏み入れることができます。

ODP.NETはデフォルトで自動コミットモードで動作するため、COMMITは簡単に発生します。

それを修正するには、

  • 自動コミットをオフにするか、
  • または、(ON COMMIT DELETE ROWSの代わりに)ON COMMITPRESERVEROWSオプションを指定して一時テーブルを使用します。
  • または通常のテーブルを使用します。
于 2012-09-18T13:01:17.533 に答える
1

接続用のトランザクションを作成し、OracleCommand オブジェクトでトランザクションを設定することもできます。

また、すべてのデータを取得する前にコミットが行われないようにします。

于 2013-12-17T18:36:31.353 に答える