I am using the Oracle Data Provider for .NET version 4.112.3.0 to access an Oracle 9 database from an ASP.NET web application. Even though I explicitly Close and Dispose of the OracleDataReader and OracleConnection objects, I receive an ORA-01000 maximum open cursors exceeded error at times.
Most of my ODP.NET code is wrapped into a custom class.
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;
}
}
}
I then use the class in my program.
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();
}
}
My query returns an average of 500 rows. When I first experienced the issue, I decided to go to the database to see how many cursors were actually opening up. The OPEN_CURSORS parameter for my database is set to 100. For a given call to the query, I noticed there were 92 open cursors for this simple select query and would break the 100 cursor limit at times! Why would such a large number of cursors open when using the OracleDataReader?
Note, I've been testing this on a development system running Windows Server 2012 with IIS 8.0. I've also called the OracleConnection.ClearAllPools method once finished with the OracleConnection, but this didn't seem to help either. I also tested the query by populating a DataTable object by using the Fill method along with an OracleDataAdapter. Using this method only opened 3 cursors. Why is there such a variation in the number of cursors opened?
Related
Hi all: I have a program that is running 4 threads that talk to an Oracle database. I have the Oracle connections local to each thread, and I'm employing the USING statement as well as manually closing the recordset and closing the connection. As I understand it, the ORA-01000 error arises when there are more open recordsets than configured cursors on the database. I do not understand why my recordsets are staying open or why I'm getting this error. Here's the code:
static void CheckPaths()
{
int pathcount = paths.Count; //paths is a typed list
Parallel.ForEach(paths, new ParallelOptions { MaxDegreeOfParallelism = 4 }, (p) =>
{
try
{
CheckSinglePathAllHours(p);
}
catch (Exception ex)
{
//there is logging here, this is where the exception hits
}
});
}
static void CheckSinglePathAllHours(Path p)
{
string sqlBase = #"Select * from table ";//this is actually a big SQL statement
using (DBManager localdbm = new DBManager())
{
string sql = sqlBase;
OracleDataReader reader = localdbm.GetData(sql);
while (reader.Read())
{
//process the path, query always returns 24 or less rows
}
reader.Close();
reader = null; //is this even necessary?
localdbm.Close(); //is this necessary in conjunction with the USING statement?
}
}
class DBManager : IDisposable
{
OracleConnection conn;
OracleCommand cmd;
public DBManager()
{
string connStr = "blah blah blah";
conn = new OracleConnection(connStr);
conn.Open();
cmd = conn.CreateCommand();
}
public OracleDataReader GetData(string sql)
{
cmd.CommandText = sql;
cmd.CommandTimeout = 900;
return cmd.ExecuteReader();
}
public void RunSQL(string sql)
{
cmd.CommandText = sql;
cmd.CommandTimeout = 900;
cmd.ExecuteNonQuery();
}
public void Close()
{
conn.Close();
}
public void Dispose()
{
try
{
conn.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
The code will usually run for about a minute or two before the exception. The exception message is two-fold: ORA-00604: error occured at recursive SQL level 1; and ORA-01000: maximum open cursors exceeded. Any ideas what I'm doing wrong?
Changed the code to call .Dispose() on OracleDataReader and OracleConnection as suggested by Paul Abbott. Also increased the number of cursors per session from 50 to 150 on the database.
I updated the code in order to simplify it
I’ve encountered a strange issue that never happened before on this code (run perfectly for 2 years).
I’m running MVC application over multiple IISs, and using MySQL over C# code.
Querying table X receives response from a different table in the same schema.
The issue happens sporadically on some IIS (once a 1-4 days) and solved by 3 iisreset.
Here is the code I’m using (updated):
using (var conn = new MySqlConnection(connectionString))
{
var command = conn.CreateCommand();
command.CommandText = sql;
IDataReader reader;
try
{
reader = command.ExecuteReader();
}
catch (Exception ex)
{
throw new MoranbernateQueryException(sql, ex);
}
using (reader)
{
while (reader.Read())
{
Console.WriteLine(sql, GetTableFromReader(reader));
}
}
}
}
private static string GetTableFromReader(IDataReader reader)
{
var schema = reader.GetSchemaTable();
var rows = schema?.Rows;
if (rows != null && schema.Columns.Count > 11)
{
return rows[0][10].ToString();
}
}
The result of this code is an sql query to table A but the table (and data) from the reader schema is B. Both tables resides in the same DB and Schema.
Has anyone else encountered this type of problem? I’d like to hear any theory or suggestion for investigation.
i don't know how do you access reader even it out of scope, there is may problem with flow of your code. use below code i think this have to work.
using(var command = new MySqlConnection(connectionString))
{
command.CommandText = sql;
try
{
using(SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
var t = new T();
var i = 0;
foreach (var property in properties)
{
try
{
property.SetValue(t, reader.GetValue(i++));
}
catch (Exception ex)
{
HandleSetValueException<T>(sql, parameters, reader, connection, ex);
}
}
yield return t;
}
}
}
catch (Exception ex)
{
throw new MoranbernateQueryException(sql, ex);
}
}
So apparently it's a known issue that was fixed by MySql team, after updating the driver all is well for now
I want open WPF program, then SQL Server database is off and when database is back online, WPF should auto connect to the database. If I restart SQL Server, keep alive program and try connect to database until connection is available. Should I catch the exception and then repeat something?
I try restart application then I got exception, but anyway my program crash and stop working.
using (SqlConnection connection = new SqlConnection(connectionString))
{
try
{
connection.Open();
}
catch (SqlException ex)
{
//how stop crash? //
//System.Windows.Forms.Application.Restart();
return ex.ToString();
}
finally
{
connection.Close();
}
}
The thing to do is to centralize the creation of connections in a single static method for your entire application.
public static SqlConnection getConnection()
{
string conn = string.Empty;
conn = System.Configuration.ConfigurationManager.ConnectionStrings["quality"].ConnectionString;
SqlConnection aConnection = new SqlConnection(conn);
return aConnection;
}
In your code,every time you use a connection try this :
public int test()
{
SqlConnection conn = null;
try
{
try
{
conn = StaticContext.getConnection();
conn.Open();
//TODO OPERATION
}
catch (Exception e)
{
//return ex.ToString();
return -1;//MY_ERROR_CODE;
}
}
finally
{
conn.Close();
}
return 1//MY_SUCCES_CODE;
}
When you call DB method manage so the error:
if (test() == -1)
{
//MESSAGE BOX ERROR OR OTHER
}
I am developing a banking application in which I have written a helper class.
What happens is whenever I continuously, 5 to 7 or more times, press the refresh button, it gives me this error: Fill: SelectCommand.Connection property has not been initialized.
Can any body specify what I am missing in my code, or what more could I do to make it better to perform without any error?
My helper class function is :
private static OdbcCommand cmd;
private static OdbcDataAdapter da;
private static DataTable dt;
public static void GetDataInDataGrid(string sp_Name, GridView gv)
{
dt = new DataTable();
try
{
using (cmd = new OdbcCommand(sp_Name))
{
cmd.Connection = Connection.ConnString.ConnectionString;
using (da = new OdbcDataAdapter(cmd))
{
da.Fill(dt);
if (dt.Rows.Count > 0)
{
gv.DataSource = dt;
gv.DataBind();
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}
The error is occurring in the below code, at the throw statement
try
{
if (!IsPostBack)
{
herlperUtility.GetDataInDataGrid("{ CALL asp_sp_GetDataForSupervisor }", this.gvSuperviseDataGrid);
if (this.gvSuperviseDataGrid.DataSource == null)
{
this.divFailure.InnerText = "No Records Found!!!";
this.divFailure.Attributes.Add("style", "display:block;margin-top:20px;");
}
}
}
catch (Exception ex)
{
throw ex;
}
Write
using (cmd = new OdbcCommand(sp_Name,Connection.ConnString.ConnectionString))
inplace of
using (cmd = new OdbcCommand(sp_Name))
{
cmd.Connection = Connection.ConnString.ConnectionString;
OracleDataAdapter hangs on Fill method in Windows XP.
While debugging In windows 7 works fine but VS2008 hangs on Windows XP.
The same applies to the release versions of the app. The sql query used has nothing to do, I have tested the function using simple queries and they all fail.
Here is a code snippet illustrating the initial code:
public static string DBSelectString(string ssql)
{
try
{
OracleDataAdapter da = new OracleDataAdapter();
DataTable dt = new DataTable();
da.SelectCommand = new OracleCommand(ssql, Connection);
da.Fill(dt);
return dt.Rows[0].ItemArray[0].ToString();
}
catch (Exception ex)
{
Utils.Log(ex.Message);
return string.Empty;
}
}
Using OracleDataReader still hangs but I managed to find a workaround.
public static string DBSelectStringDR(string ssql)
{
OracleDataReader reader = null;
try
{
Connection.Open();
OracleCommand command = new OracleCommand(ssql, Connection);
reader = command.ExecuteReader();
if (reader.HasRows)
{
//reader.Read();
//return reader.GetValue(0).ToString(); <-------- normally hangs here
try
{
//workaround:
//force exception, since Read has not been executed
string test = reader.GetValue(0).ToString();
}
catch { }
// then, everything works fine
reader.Read();
return reader.GetValue(0).ToString();
}
else
{
return string.Empty;
}
}
catch (Exception ex)
{
Utils.Log(ex.Message);
return string.Empty;
}
finally
{
if (reader != null) reader.Close();
Connection.Close();
}
}
Any ideas ?