System.ObjectDisposedException: Cannot access a disposed object. Object name: 'OracleConnection' Reuse of OracleConnection object

StackOverflow https://stackoverflow.com/questions/16077666

Question

I would to reuse a OracleConnection object for more queries so I wrote a simple class:

public static class DbConnectionsManager
    {
        /// <summary>
        /// 
        /// </summary>
        private static OracleConnection _dbConnection = null;


        /// <summary>
        /// 
        /// </summary>
        /// <param name="aConnectionString"></param>
        /// <returns></returns>
        public static OracleConnection GetDatabaseConnection(string aConnectionString) 
        {
            try
            {
                if (_dbConnection == null)
                {
                    _dbConnection = new OracleConnection(aConnectionString);
                    _dbConnection.Open();
                    return _dbConnection;
                }

                if (_dbConnection.State == System.Data.ConnectionState.Closed)
                {
                    _dbConnection.ConnectionString = aConnectionString;
                    _dbConnection.Open();
                    return _dbConnection;
                }

                if (!_dbConnection.ConnectionString.Equals(aConnectionString))
                {
                    _dbConnection.Close();
                    _dbConnection.ConnectionString = aConnectionString;
                    _dbConnection.Open();
                    return _dbConnection;
                }

                return null;
            }
            catch (Exception e)
            {

                return null;
            }
        }
    }

in this way I can use the connection several times:

  using (OracleConnection connection = 
           DbConnectionsManager.GetDatabaseConnection(aDbConnectionString))
            {
                OracleCommand command = connection.CreateCommand();
                string sql = "SELECT * FROM MYTABLE";
                command.CommandText = sql;

                OracleDataReader reader = command.ExecuteReader();
                while (reader.Read())
                {
                    string myField = (string)reader["EXAMPLE"];
                    Console.WriteLine(myField);
                }
            }

When I call the method the first time everything works fine. If I recall the method the static object is != null but the connection result closed! I never close the connection!

When you try to reopen the connection I have this exception

....
if (_dbConnection.State == System.Data.ConnectionState.Closed)
                {
                    _dbConnection.ConnectionString = aConnectionString;
                    _dbConnection.Open();
                    return _dbConnection;
                }
...

Error

Message = "Cannot access a disposed object.\r\nObject name: 'OracleConnection'."
Was it helpful?

Solution

As the error says it's a disposed object. That means you need to remove the using ( clause; this clause disposed your connection object and that's why you cannot use this object outside using (. That means you need to create a new object of class if you want to use it outside using (.

See: C# Using Statement

OTHER TIPS

As the other answer explains, the using clause isn't a natural fit for something you're wanting to re-use. However I had the same idea - I would still like to use this type of pattern to auto-open & auto-close the connection. If that is what you were hoping to do, then the key is that the object you are "using" cannot be the OracleConnection itself since you do want to reuse this, and "using" it will kill it. You really just want a new object which opens the connection on creation, and closes the connection on Dispose, and nothing more. This should do the trick (I am using it for my own purposes):

internal class OpenedContext : IDisposable
{
    private OracleConnection _connection;

    public OpenedContext(OracleConnection conn) {
        _connection = conn;
        if (_connection.State != System.Data.ConnectionState.Open) _connection.Open();            
    }

    public void Dispose() {
        if (_connection.State != System.Data.ConnectionState.Closed) _connection.Close();
    }

}

And then in your example you could do something like...

            // Early on...
            OracleConnection _connection = DbConnectionsManager.GetDatabaseConnection(aDbConnectionString);

            // ... Later on, in various other calls ...
            using (new OpenedContext(_connection))
            {
                OracleCommand command = _connection.CreateCommand();
                string sql = "SELECT * FROM MYTABLE";
                command.CommandText = sql;
                OracleDataReader reader = command.ExecuteReader();
                while (reader.Read())
                {
                    string myField = (string)reader["EXAMPLE"];
                    Console.WriteLine(myField);
                }
            }

Although it's goofy in a way, I definitely prefer setting up a pattern like this to always expecting future coders to manually "wrap" the re-open & re-close around every database call. It's more readable (or ignorable) and less risky (if you're greatly concerned about leaving the connection closed while idle).

public OracleConnection GetConnection()
{

//Romove using(...) clouse 
using (OracleConnection conn = new OracleConnection(_connSettings.GetConnectionString()))
{return con;}

The issue is inner using() clause problem.

using (OracleConnection con = GetConnection()){}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top