使用ODP.NET C#OracleDataReader的最大开放游标ORA-01000
我正在使用Oracle Data Provider for.NET 4.112.3.0版从ASP.NET web应用程序访问Oracle 9数据库。即使我显式地使用ODP.NET C#OracleDataReader的最大开放游标ORA-01000,c#,asp.net,oracle,odp.net,C#,Asp.net,Oracle,Odp.net,我正在使用Oracle Data Provider for.NET 4.112.3.0版从ASP.NET web应用程序访问Oracle 9数据库。即使我显式地OracleDataReader和OracleConnection对象的Close和Dispose,我仍会收到ORA-01000最大打开游标数,有时会出现错误 我的大部分ODP.NET代码都包装到自定义类中 using System; using System.Collections.Generic; using System.Linq;
OracleDataReader
和OracleConnection
对象的Close
和Dispose
,我仍会收到ORA-01000最大打开游标数,有时会出现错误
我的大部分ODP.NET代码都包装到自定义类中
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Oracle.DataAccess.Client;
using System.Data;
namespace MyNamespace
{
public class MyOracleClass : IDisposable
{
private static string connectionString = "Data Source=myDB;Persist Security Info=True;User ID=myUser;Password=myPassword;";
private OracleConnection _conn;
private OracleTransaction _txn;
public MyOracleClass()
{
try
{
_conn = new OracleConnection(connectionString);
if (_conn.State != ConnectionState.Open)
_conn.Open();
_txn = _conn.BeginTransaction(IsolationLevel.ReadCommitted);
}
catch (Exception ex)
{
// Log Exception
throw ex;
}
}
public void Query(string query, ref OracleDataReader dr)
{
dr = null;
OracleCommand cmd = null;
try
{
if (_conn.State != ConnectionState.Open)
_conn.Open();
cmd = new OracleCommand(query, _conn);
dr = cmd.ExecuteReader();
}
catch (Exception ex)
{
// Log Exception
throw ex;
}
finally
{
if (cmd != null)
cmd.Dispose();
}
}
public void Disconnect()
{
try
{
if (IsConnectionOpen())
{
_txn.Rollback();
_conn.Close();
}
}
catch (Exception ex)
{
// Log Exception
}
}
public void Dispose()
{
Disconnect();
try
{
if (this._txn != null)
{
_txn.Dispose();
_txn = null;
}
}
catch (Exception ex)
{
// Log Exception
}
try
{
if (this._conn != null)
{
this._conn.Dispose();
}
}
catch (Exception ex)
{
// Log Exception
}
}
public bool IsConnectionOpen()
{
if (this._conn.State == ConnectionState.Open)
{
return true;
}
return false;
}
}
}
然后我在程序中使用该类
public void test()
{
OracleDataReader dr = null;
MyOracleClass oracleDb = null;
string query = "SELECT COL_1, COL_2, COL_3 FROM MY_TABLE";
try
{
oracleDb = new MyOracleClass();
oracleDb.Query(query, ref dr);
if(!dr.HasRows)
{
// No data found
}
else
{
while(dr.Read())
{
// Process data
}
}
}
catch(Exception ex)
{
// Log Exception
}
finally
{
if(dr != null)
{
dr.Close();
dr.Dispose();
}
oracleDb.Dispose();
}
}
我的查询平均返回500行。当我第一次遇到这个问题时,我决定去数据库看看实际打开了多少个游标。我的数据库的OPEN\u CURSORS
参数设置为100。对于给定的查询调用,我注意到这个简单的select查询有92个打开的游标,有时会突破100个游标的限制!为什么在使用OracleDataReader
时会打开如此多的游标
注意,我已经在一个运行WindowsServer2012和IIS8.0的开发系统上测试了这一点。使用
OracleConnection
完成后,我还调用了OracleConnection.ClearAllPools
方法,但这似乎也没有什么帮助。我还通过使用Fill
方法和OracleDataAdapter
填充DataTable
对象来测试查询。使用此方法仅打开3个游标。为什么打开的游标数量会有这样的变化?为什么需要为select?@Dr.Stitch打开一个事务?MyOracleClass中有另一个方法调用ExecuteOnQuery进行插入/删除/更新,因此OracleTransaction用于提交和回滚。为了简洁起见,我删除了代码。