gpt4 book ai didi

c# - Command.Prepare() 导致内存泄漏?

转载 作者:搜寻专家 更新时间:2023-10-30 20:06:39 26 4
gpt4 key购买 nike

我继承了这个科学建模项目的一些代码,我和我的同事都被这个问题难住了。写这篇文章的人现在已经不在了,所以我们不能问他(想想看)。

在数据访问层内部,有这个insert()方法。这就像它听起来的那样——它将记录插入到数据库中。在模拟过程中,被建模的各种对象使用它来告诉数据库关于它们自己的信息。

但是,我们注意到,在插入相当数量的数据库后的较长模拟过程中,我们最终会遇到连接超时。所以我们提高了超时限制,然后我们开始从 PostgreSQL 收到“内存不足”错误。我们最终将问题定位到 IDbCommand 对象使用 Prepare() 的那一行。保留它会导致内存使用量无限增加。注释掉这一行会使代码正常工作,并消除所有内存问题。 Prepare() 做了什么导致了这个?我在文档中找不到任何内容来解释这一点。

代码的压缩版本如下。

public virtual void insert(DomainObjects.EntityObject obj)
{
lock (DataBaseProvider.DataBase.Connection)
{
IDbCommand cmd = null;
IDataReader noInsertIdReader = null;
IDataReader reader= null;

try
{
if (DataBaseProvider.DataBase.Validate)
{ ... }

// create and prepare the insert command
cmd = createQuery(".toInsert", obj);
cmd.Prepare(); // This is what is screwing things up

// get the query to retreive the sequence number
SqlStatement lastInsertIdSql = DAOLayer...getStatement(this.GetType().ToString() + ".toGetLastInsertId");

// if the obj insert does not use a sequence, execute the insert command and return
if (lastInsertIdSql == null)
{
noInsertIdReader = cmd.ExecuteReader();
noInsertIdReader.Close();
return;
}

// append the sequence query to the end of the insert statement
cmd.CommandText += ";" + lastInsertIdSql.Statement;

reader = cmd.ExecuteReader();

// read the sequence number and set the objects id
...
}

// deal with some specific exceptions
...
}
}

编辑:(响应第一个给出的答案)所有数据库对象都在 finally block 中处理。为了节省空间,我只是把那部分剪掉了。我们对此进行了一些尝试,但没有任何区别,所以我认为这不是问题所在。

最佳答案

您会注意到 IDbCommand 和 IDataReader 都实现了 IDisposable .无论何时创建 IDisposable 对象的实例,您都应该将其包装在 using statement 中。或调用Dispose一旦你完成了。如果不这样做,您最终会泄漏资源(有时是内存以外的资源)。

在你的代码中试试这个

using (IDbCommand cmd = createQuery(".toInsert", obj))
{
cmd.Prepare(); // This is what is screwing things up
...
//the rest of your example code
...
}

编辑以专门讨论准备

我可以从代码中看出您正在准备命令,但从未重复使用它。

准备命令背后的想法是,它会花费额外的开销来准备,但每次使用命令时,它都会比未准备好的语句更有效。如果您有一个要重复使用的命令,这很好,并且可以权衡开销是否值得命令的性能提升。

所以在您向我们展示的代码中,您正在准备命令(支付所有开销)并且没有得到任何好处,因为您随后立即丢弃了命令!

我要么回收准备好的命令,要么放弃对准备语句的调用。

我不知道为什么准备好的命令会泄漏,但你一开始就不应该准备这么多命令(尤其是一次性命令)。

关于c# - Command.Prepare() 导致内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3535132/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com