我正在将 .net 应用程序从 SqlServer 移植到 Oracle 12c。我正在使用非托管 64 位 ODAC 12c Release 2 (12.1.0.1.2) 客户端访问数据库。
Oracle 12c 引入了 DBMS_SQL.RETURN_RESULT(cur) 函数,它允许我按原样重用 .net 代码,而无需向 ado.net 命令添加特定的输出参数。这是我的代码的一个片段:
using (var command = CreateCommand("uspGetAllNumericUnits", CommandType.StoredProcedure))
{
using (var connectionScope = command.Connection.CreateConnectionScope())
{
using (var reader = command.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
....
}
}
}
}
}
uspGetAllNumericUnits 存储过程就像:
PROCEDURE uspGetAllNumericUnits_RPT
AS
cv_1 SYS_REFCURSOR;
BEGIN
OPEN cv_1 FOR
SELECT * FROM NumericUnit;
DBMS_SQL.RETURN_RESULT(cv_1);
END;
我相信我正确地处理了 dbReader 和 dbCommand,并且连接也被 connectionScope 关闭和处理了。但是,如果我检查服务器上的 v$open_cursor 视图,我会看到“SELECT * FROM NumericUnit;”的光标 保持打开状态。我使用连接池,如果我禁用它(我不想这样做),光标会在 connectionScope 被释放时正确关闭。
我的问题是我有很多像这样的 ado.net 调用,我很快就达到了每个会话允许的最大游标限制,并引发了 ORA-01000 错误。
如果我使用旧的 Oracle 11g 方法,将结果集游标作为输出参数返回,并且不使用 DBMS_SQL.RETURN_RESULT(cv_1) 函数,则无论连接池与否,都会在释放 connectionScope 时正确关闭游标。
我需要一些额外的对象来处理隐式引用游标的关闭吗?这是一个已知的 ODAC 12cR2 错误吗?DBMS_SQL.RETURN_RESULT(cv_1) 的引入使得从 SqlServer 到 Oracle 的移植比几乎在任何地方都必须添加输出参数更容易,但我不想摆脱连接池。