c# - Oracle ODP.NET 游标泄漏?

标签 c# oracle odp.net database-cursor

我在使用以下代码时遇到了打开游标限制问题。 oracle db 上的打开游标限制设置为大约 1000。以下代码似乎保留在游标上,即使我已经在 using 语句(我认为)中获得了需要它的所有内容。 (注意,我不需要从 outRefCursor2 读取任何内容)

我是否遗漏了 using 或其他使用 ODP.net 进行的清理?
异常始终出现在迭代 596。

static List<Thing> GetDetailsForItems(List<string> items) {
  DateTime start = DateTime.UtcNow;
  var things = new List<Thing>();
  var spname = "SP_GET_THING_DETAILS";
  var outRefCursorName1 = "p_ref_cursor1";
  var outRefCursorName2 = "p_ref_cursor2";

  // Create params
  var pInput1 = new OracleParameter("p_input1",
                  OracleDbType.Varchar2, ParameterDirection.Input);
  pInput1.Value = "";
  // Input 2 can be blank
  var pInput2 = new OracleParameter("p_input2",
                  OracleDbType.Varchar2, ParameterDirection.Input);
  pInput2.Value = "";

  var outRefCursor1 = new OracleParameter(outRefCursorName1,
                  OracleDbType.RefCursor, ParameterDirection.Output);
  var outRefCursor2 = new OracleParameter(outRefCursorName2,
                  OracleDbType.RefCursor, ParameterDirection.Output);

  int count = 0;
  using (var conn = new OracleConnection(CONN_STR)) {
    conn.Open();
    using (var cmd = conn.CreateCommand()) {
      cmd.Parameters.Add(pInput1);
      cmd.Parameters.Add(pInput2);
      cmd.Parameters.Add(outRefCursor1);
      cmd.Parameters.Add(outRefCursor2);
      cmd.CommandText = spname;
      cmd.CommandType = CommandType.StoredProcedure;
      foreach (string value in items) {
        count++; 
        cmd.Parameters[pInput1.ParameterName].Value = value;
        var execVal = cmd.ExecuteNonQuery();
        using (var refCursor = (Types.OracleRefCursor)
                                cmd.Parameters[outRefCursorName1].Value) {
          using (var reader = refCursor.GetDataReader()) {
            while (reader.Read()) {
              // read columns
              things.Add(reader["COLUMN_A"].ToString());
            }
          } // close reader
        } // close cursor
      } // end foreach
    } // close command
  } // close connection           
  int seconds = (DateTime.UtcNow - start).Seconds;
  Console.WriteLine("Finished in {0} seconds", seconds);
  return things;
}

我正在使用在线找到的这个片段来监控数据库游标。我可以在单步执行代码时看到游标加起来。他们只是不断地在 cmd.ExecuteNonQuery() 行添加。在任何 using 语句关闭后,我从未看到下降。

select sum(a.value) total_cur, avg(a.value) avg_cur, max(a.value) max_cur, 
s.username, s.machine
from v$sesstat a, v$statname b, v$session s 
where a.statistic# = b.statistic#  and s.sid=a.sid
and b.name = 'opened cursors current'
and machine='MY COMPUTER' 
group by s.username, s.machine
order by 1 desc;

最佳答案

即使您没有使用 outRefCursor2,如果它返回有效游标,您仍然需要提取它并关闭它。 ODP.net 处理资源的方式不如 .Net 版本,因此您需要确保处理 ODP.net 命令返回的一切。作为一个额外的步骤,在游标上显式调用 .Close() 可能不会有什么坏处,以确保您实际上正在关闭它们(尽管 dispose 应该处理这一点)。

关于c# - Oracle ODP.NET 游标泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7588689/

相关文章:

c# - 添加自动属性会影响远程处理吗?

c# - 如何在我的代码中处理 IDisposable?

oracle - Toad for Oracle..如何执行多条语句?

oracle - 无法在 PLSQL 中使用 REPLACE 函数

c# - 如何知道何时停止填充 OracleDataAdapter

perfmon中缺少ODP.NET托管驱动程序性能计数器

c# - Oracle 号码映射 (ODP.NET)

c# - MVVM 列表和 ObservableCollection

c# - 如何停止自动使用 Tag Helper?

java - 结果集不包含行?