System.ObjectDisposedException:无法访问已释放的对象.对象名称:';OracleCo
本文关键字:对象 OracleCo 释放 ObjectDisposedException 访问 System | 更新日期: 2023-09-27 18:09:41
我想为更多的查询重用OracleConnection对象所以我写了一个简单的类:
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;
}
}
}
通过这种方式,我可以多次使用连接:
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);
}
}
当我第一次调用该方法时,一切都很好。如果我回忆起静态对象的方法!=null,但连接结果已关闭!我从不关闭连接!
当你试图重新打开连接时,我有这个异常
....
if (_dbConnection.State == System.Data.ConnectionState.Closed)
{
_dbConnection.ConnectionString = aConnectionString;
_dbConnection.Open();
return _dbConnection;
}
...
错误
Message = "Cannot access a disposed object.'r'nObject name: 'OracleConnection'."
因为错误表明它是一个已处理的对象。这意味着您需要删除using (
子句;这个子句处理了你的连接对象,这就是为什么你不能在using (
之外使用这个对象。这意味着您需要创建一个类的新对象,如果您想在using (
之外使用它。
请参阅:C#使用语句
正如另一个答案所解释的,using
子句并不适合您想要重用的东西。然而,我有同样的想法——我仍然想使用这种类型的模式来自动打开&自动关闭连接。如果这是你希望做的,那么关键是你"使用"的对象不能是OracleConnection本身,因为你do想要重用它,而"使用"它会杀死它。你真的只想要一个新对象,它在创建时打开连接,在Dispose时关闭连接,仅此而已。这应该做的技巧(我使用它为我自己的目的(:
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();
}
}
然后在你的例子中,你可以做一些事情,比如。。。
// 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);
}
}
虽然这在某种程度上很愚蠢,但我肯定更喜欢设置这样的模式,而不是总是期望未来的程序员手动"包装"重新打开的&重新关闭每个数据库调用。它更可读(或可忽略(,风险更小(如果你非常担心在空闲时关闭连接(。
public OracleConnection GetConnection()
{
//Romove using(...) clouse
using (OracleConnection conn = new OracleConnection(_connSettings.GetConnectionString()))
{return con;}
问题是内部using((子句问题。
using (OracleConnection con = GetConnection()){}