C# DB2Connection对象循环打开然后关闭内存异常

C# DB2Connection对象循环打开然后关闭内存异常,c#,.net,memory,db2,db2-luw,C#,.net,Memory,Db2,Db2 Luw,我正在使用IBM.Data.DB2.DB2DataAdapter对象与不同服务器上的不同数据库建立多个连接。 我的基本循环和连接结构如下所示: foreach (MyDBObject db in allDBs) { //Database Call here for current DB...//Get SQL, then pass it to DB call QueryCurrentDB(command); } 然后 DB2Connection _connection;

我正在使用IBM.Data.DB2.DB2DataAdapter对象与不同服务器上的不同数据库建立多个连接。
我的基本循环和连接结构如下所示:

foreach (MyDBObject db in allDBs)
{
    //Database Call here for current DB...//Get SQL, then pass it to DB call
    QueryCurrentDB(command);
}
然后

DB2Connection _connection;    

Public DataTable QueryCurrentDB(DB2Command command)
{

    _connection = new DB2Connection();
    DB2DataAdapter adapter = new DB2DataAdapter();

    _connection.ConnectionString = string.Format("Server={0};Database={1};UID={2};PWD={3};", _currentDB.DBServer, _currentDB.DBName, _currentDB.UserCode, _currentDB.Password);
    command.CommandTimeout = 20;
    command.Connection = _connection;
    adapter.SelectCommand = command;                
    _connection.Open();

    adapter.Fill(dataTable);

    _connection.Close();
    _connection.Dispose();

    return dataTable;
}
如果我在不同的服务器上有大约20个数据库,我最终会得到这个异常。我也无法控制每个db实例的内存分配

错误[57019][IBM]SQL1084C数据库管理器无法分配共享内存,因为已达到操作系统内核内存限制。SQLSTATE=57019

我唯一能够解决这个问题的方法是在每次db调用之前放置一个线程睡眠,例如:

System.Threading.Thread.Sleep(3000);

我讨厌这一点,任何建议都将不胜感激。

在发布的代码中,
连接
命令
数据适配器
都是
IDisposable
,表明它们需要释放以释放分配的资源。但实际上只处理了
DBConnection
对象。特别是在像您这样的回路中,处理这些部件以防止泄漏非常重要

我没有DB2提供程序,但它们的工作原理基本相同,特别是在这方面。我将从重构代码开始,从
MyDBObject
开始。与其只保留连接字符串参数,不如让它为您创建连接:

然后循环方法:

// this also could be a method in MyDbObject
public DataTable QueryCurrentDB(string SQL)
{
    DataTable dt = new DataTable();
    using (DB2Connection dbcon = currentDB.GetConnection())
    using (DB2Command cmd = new DB2Command(SQL, dbcon))
    {
        cmd.CommandTimeout = 20;
        dbcon.Open();
        dt.Load(cmd.ExecuteReader());
    }
    return dt;
}
  • 最重要的是,请注意,
    IDisposable
    对象都包含在
    using
    块中。这将处置(并关闭)目标并释放任何分配的资源
  • 填写表格不需要
    DataAdapter
    。省略它意味着少创建一个
    IDisposable
    对象
  • 与其传入命令,不如传入SQL。这还允许您创建、使用和处置
    DBCommand
    对象
  • 如果同一数据库中有两个表有可能被轮询,我会进一步重构,以使在同一连接上填充两个表成为可能
之前:3个对象中有2个未被处置(每次迭代!)
之后:处置2个对象中的2个

我怀疑罪魁祸首是
DBCommand
对象(类似于),但可能是它们的组合

将线程置于睡眠状态(可能)是有效的,因为它使GC有机会赶上清理工作。你可能还没有走出困境。上面的链接在400次迭代中遇到了问题;20个甚至40个(20*2个对象)似乎是消耗资源的一个非常小的数字


因此,我怀疑代码的其他部分也未能正确处理,而循环只是压垮骆驼背的稻草。查找正在使用的其他循环和DB对象,并确保将其处理掉。基本上,任何具有
Dispose()
方法的内容都应该在
using
块中使用

代码没有给出清晰的图片(未使用传递的
sqlCommand
,并且未显示如何/在何处创建
\u连接
)。但是错误消息并没有明确地暗示
DBConnection
。DBProvider对象需要处理,但看起来不像您。我更新了代码,以更好地展示我如何使用db2对象。我将在今天的某个时候更改代码并测试您的建议。我会让你知道它是如何运行的,谢谢。我用using语句包装了所有的db对象,并使用我20多个不同的db连接和查询,到目前为止它工作得非常好,没有任何线程休眠。谢谢很高兴听到。请记住,问题中的代码实际上只是揭示了问题。我认为该应用程序能够负担得起20-40个对象的精简,因此其他地方的代码也可能泄漏。真正的关键是答案中的最后一句话:“任何具有
Dispose()
方法的东西都应该在using块中使用”
// this also could be a method in MyDbObject
public DataTable QueryCurrentDB(string SQL)
{
    DataTable dt = new DataTable();
    using (DB2Connection dbcon = currentDB.GetConnection())
    using (DB2Command cmd = new DB2Command(SQL, dbcon))
    {
        cmd.CommandTimeout = 20;
        dbcon.Open();
        dt.Load(cmd.ExecuteReader());
    }
    return dt;
}