Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SqlCommand.Dispose()未处理其中的SqlParameters-内存泄漏-C#.NET_C#_Memory Leaks_Sqlcommand - Fatal编程技术网

SqlCommand.Dispose()未处理其中的SqlParameters-内存泄漏-C#.NET

SqlCommand.Dispose()未处理其中的SqlParameters-内存泄漏-C#.NET,c#,memory-leaks,sqlcommand,C#,Memory Leaks,Sqlcommand,我有一个windows窗体应用程序,后台是MS SQL Server 2005。我已经编写了使用SqlConnection、SqlCommand对象调用一些存储过程的代码,并且我正确地处理了所有内容 我已通过调用 oSqlCommand.Dispose() 但我看到我的应用程序消耗了大量内存。基本上,我将大型XML文件作为SqlParameters传递 最后,我决定使用RedGate内存分析器对其进行内存分析,我注意到,System.Data.SqlClient.SqlParameters没有

我有一个windows窗体应用程序,后台是MS SQL Server 2005。我已经编写了使用SqlConnection、SqlCommand对象调用一些存储过程的代码,并且我正确地处理了所有内容

我已通过调用

oSqlCommand.Dispose()
但我看到我的应用程序消耗了大量内存。基本上,我将大型XML文件作为SqlParameters传递

最后,我决定使用RedGate内存分析器对其进行内存分析,我注意到,
System.Data.SqlClient.SqlParameters
没有被释放

对此有什么见解吗

谢谢


NLV

Dispose不处理它的参数,只处理它的内部SqlMetaData缓存。。。顺便说一句,参数不会自动释放是正常的,因为在释放命令后,您可能会传入一些不应该释放的内容…+SqlParameter也没有实现Dispose,因为它不包含非托管资源….

我看到了以下情况:

我妥善处理一切

这是:

我通过调用
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
现在,我从这个问题得出结论,这不是目前的主要问题,但这是一个值得开车回家的问题

关于参数的问题:SqlParameters没有实现IDisposable。因此,您不能直接处理它们。它们是一种完全受管理的资源,这意味着在无法访问它们之后,它们会在某个时候被垃圾收集器清除。你不必做任何事情来自己清理它们

如果您可以认真地表明SqlParameter对象在它们应该挂起的时间之后很久才挂起,这意味着您在某处持有对它们的引用。例如,您可能正在某处“缓存”旧的SqlCommand对象,而这些对象又保留了它们的所有参数。不要那样做。找到并消除仍然引用SqlParameters的内容,垃圾收集器将为您清理它们

更新:
在重读您的问题之后,听起来xml参数最终会出现在大型对象堆上。Net中的垃圾收集器是分代的,它不会在每次运行时都清理所有东西。当一个物体移动到更高的一代时,它更可能会停留一段时间。大型对象堆基本上是最后一代,根本没有得到太多清理。更重要的是,它永远不会被压缩,以至于随着时间的推移它会碎裂。这可能导致程序保留的数据远远超过其需要的数据量。您需要做的是设法避免将参数的整个xml数据加载到内存中,这样它就永远不会进入大型对象堆。使用文件流或类似的东西来代替。

如果不进行测试,我可以想到两件可能对您有所帮助的事情。使用
SqlParameters
可以使用
finalize()
方法来释放资源。您是否也在使用块通过
运行所有Sql命令?如果是这样,当使用块完成时,您的资源应该被回收,它将消除内存泄漏问题。

由于
SqlParameter
不可
IDisposable
,因此不存在处理它的问题;通常情况下,整理引用等不会有什么好处,因为它仍然受相同的GC约束


如果听起来像是您意外地保留了对
SqlCommand
的引用。但是,如果您确信完成了,您可以尝试显式地将每个
.Value
设置为
null
,并在参数列表上调用
Clear()
。但这实际上只是掩盖了这样一个事实,即您正在死死地执行一个命令。

我使用的这种模式是几个没有任何问题的项目

public partial class StoredProcedures
{
    [SqlProcedure()]
    public static void InsertCurrency_CS(
        SqlString currencyCode, SqlString name)
    {
        using (SqlConnection conn = new SqlConnection("context connection=true"))
        {
            SqlCommand InsertCurrencyCommand = new SqlCommand();
            SqlParameter currencyCodeParam = new SqlParameter("@CurrencyCode", SqlDbType.NVarChar);
            SqlParameter nameParam = new SqlParameter("@Name", SqlDbType.NVarChar);



            InsertCurrencyCommand.CommandText =
                "INSERT Sales.Currency (CurrencyCode, Name, ModifiedDate)" +
                " VALUES(@CurrencyCode, @Name)";

            InsertCurrencyCommand.Connection = conn;

            conn.Open();
            InsertCurrencyCommand.ExecuteNonQuery();
            conn.Close();
        }
    }
}

ref:

如果确定是SqlParameter保留了最后一个引用,那么可以做几件事

首先,尝试将XML作为字符串传递(并在存储过程中使用OPENXML来处理它),看看使用简单的对象和更多的控件是否会有所帮助

其次,制作您自己的SqlParameter-s,将它们保存在字典中,然后执行以下操作:

foreach (SqlParameter param in parameters.Values)
    command.Parameters.Add(param);
然后,在完成该命令后,运行并释放该命令,关闭(如果仍然打开)并释放连接,进入字典,显式地将null指定为SqlParameter.Value(或者,将字符串ref from.Value放入本地变量,将字符串.Empty赋值给.Value,然后将null赋值给本地变量——只有当SqlParameter.Value抱怨直接为null时,才会这样做。然后将null赋值给字典项(这是对SqlParameter的引用),然后将null赋值给字典

在更简单的情况下,您可以只保留对该关键SqlParameter的引用并跳过字典。关键点是保持显式地将null赋值——最后一个引用赋给字符串,然后将最后一个引用赋给包含该字符串的SqlParameter

请记住,这涉及到几件事。它从根本不在中间层解析XML开始——只是将其发送到SQL,然后以显式地取消引用结束。如果您的代码实际上是在动态构造XML,请将其作为一个大的直字符串来尝试

如果单靠这一点并不能降低内存压力,那么您将不得不强制执行显式GC收集,但为此,您必须进行一些读取并计划合理的时间间隔,因为GC成本很高,即,如果您像疯兔子一样在每个请求后启动GC,您将在CPU周期中付出大量代价

A