SqlCommand.Dispose()没有在其中部署SqlParameters - 内存泄漏 - C#.NET

NLV*_*NLV 5 c# memory-leaks sqlcommand

我有一个Windows窗体应用程序与MS SQL Server 2005作为后端.我已经在表单中编写代码,使用SqlConnection,SqlCommand对象调用一些存储过程,并且我正确地处理了所有内容.

我通过调用处理了sqlcommand对象

oSqlCommand.Dispose()
Run Code Online (Sandbox Code Playgroud)

但我目睹了我的应用程序消耗了大量的内存.我基本上将大型XML文件作为SqlParameters传递.

我终于决定使用RedGate内存分析器对内存进行配置文件,我注意到它System.Data.SqlClient.SqlParameters没有被处理掉.

有什么见解吗?

谢谢

NLV

Joe*_*orn 15

我看到了这个:

我妥善处理一切.

还有这个:

我通过调用处理了sqlcommand对象 oSqlCommand.Dispose()

但是,那些是相互排斥的!如果你.Dispose()直接打电话,那你做错了.具体来说,您可以保留异常将使程序跳过对Dispose()方法的调用的可能性.处理命令的"正确"方法使用using块创建它,如下所示:

using (SqlCommand cmd = new SqlCommand("sql string here"))
{
    // use the command here
} // compiler transforms your code to make sure .Dispose() is called here
Run Code Online (Sandbox Code Playgroud)

现在,我从这个问题中收集到这不是目前的主要问题,但这是一个值得回家的点.

至于有关参数的问题:SqlParameters不实现IDisposable.因此,您不要直接处理它们.它们是一个完全受管理的资源,这意味着它们在垃圾收集器不再可用后的某个时刻被垃圾收集器清理干净.您无需做任何事情来自行清理它们.

如果你能够认真地证明SqlParameter对象在它们之后很久就会挂起,那就意味着你在某个地方持有对它们的引用.例如,也许您正在某处"缓存"旧的SqlCommand对象,而这些对象又会保留所有参数.不要那样做.查找并消除仍然引用SqlParameters的内容,垃圾收集器将为您清理它们.

更新:

重新阅读您的问题后,听起来xml参数最终会出现在大对象堆上..Net中的垃圾收集器是世代的 - 它不会在每次运行时清理所有内容.随着对象移动到更高的一代,它更有可能暂停一段时间.大对象堆基本上是最后一代,它根本没有被清理干净.更重要的是,它不会被压缩,因此随着时间的推移它会碎片化.这可能导致程序保留比需要更多的数据.您需要做的是尝试找到一种方法来防止将参数的整个xml数据加载到内存中,这样它就不会进入大对象堆.使用文件流或类似的东西.


Mar*_*ell 6

既然SqlParameter不是IDisposable,那就不是处理它的问题; 并且通常在整理参考文献等方面没有什么好处,因为它仍然受到同一个GC的影响.

如果听起来像你不小心保留了参考SqlCommand.但是,如果你确信你完成,你可以尝试明确每个设置.Valuenull,并调用Clear()的参数列表.但这实际上只是掩盖了你坚持死命令的事实.