我使用Oracle Data Provider for .NET 4.112.3.0版从ASP.NET Web应用程序访问Oracle 9数据库。即使我明确Close
和Dispose
OracleDataReader
和OracleConnection
个对象,我有时会收到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_CURSORS
参数设置为100.对于给定的查询调用,我注意到这个简单的select查询有92个打开的游标,有时会打破100个游标限制!使用OracleDataReader
?
注意,我一直在运行带有IIS 8.0的Windows Server 2012的开发系统上测试它。我在使用OracleConnection.ClearAllPools
完成后也调用了OracleConnection
方法,但这似乎也没有帮助。我还通过使用DataTable
方法和Fill
填充OracleDataAdapter
对象来测试查询。使用此方法仅打开3个光标。为什么打开游标的数量有这么大的差异?