SqlCommand. Расположите () не расположение SqlParameters в нем - Утечку памяти - C#.NET

У меня есть приложение форм окон с SQL Server MS 2005 как бэкэнд. Я написал код в форме для вызова небольшого количества использования хранимых процедур SqlConnection, объектами SqlCommand, и я правильно располагаю все.

Я расположил объект sqlcommand путем вызова

oSqlCommand.Dispose()

Но я засвидетельствовал свое приложение, использующее огромный объем памяти. Я в основном передаю большие XML-файлы как SqlParameters.

Я наконец решил к профилю памяти это использование профилировщик Памяти RedGate, и я заметил что System.Data.SqlClient.SqlParameters не расположены.

Какое-либо понимание на этом?

Спасибо

NLV

5
задан NLV 9 June 2010 в 19:13
поделиться

5 ответов

Я вижу следующее:

Я все правильно утилизирую.

и это:

Я удалил объект 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

Теперь я понимаю из вопроса, что это не главная проблема на данный момент, но это вопрос, о котором стоит поговорить.

Что касается вопроса о параметрах: SqlParameters не реализует IDisposable . Следовательно, вы не выбрасываете их напрямую. Это полностью управляемый ресурс, а это означает, что они очищаются сборщиком мусора в какой-то момент после того, как становятся недоступными. Вам не нужно ничего делать, чтобы очистить их самостоятельно.

Если вы всерьез можете показать, что объекты SqlParameter существуют намного позже, чем следовало бы, это означает, что вы где-то держите ссылку на них. Например, возможно, вы где-то «кешируете» старые объекты SqlCommand, которые, в свою очередь, сохраняют все свои параметры. Не делай этого. Найдите и удалите все, что еще ссылается на SqlParameters, и сборщик мусора очистит их за вас.

Обновление:

После перечитывания вашего вопроса выясняется, что параметры xml попадают в кучу больших объектов. Сборщик мусора в .Net является поколенческим - он не очищает все при каждом запуске. По мере того, как объект переходит к более высокому поколению, он с большей вероятностью задержится какое-то время. Куча больших объектов, по сути, является последним поколением, и она совсем не очищается. Более того, он никогда не уплотняется, так что со временем он фрагментируется. Это может привести к тому, что программа будет хранить гораздо больше данных, чем ей нужно. Что вам нужно сделать, так это попытаться найти способ избежать загрузки всех XML-данных для параметра в память, чтобы они никогда не попадали в кучу больших объектов. Вместо этого используйте файловый поток или что-то подобное.

15
ответ дан 18 December 2019 в 06:34
поделиться

Поскольку SqlParameter не является IDisposable , его удаление не является проблемой; и обычно будет мало пользы в приведении в порядок ссылок и т. д., поскольку это все еще подчиняется тому же GC.

Если звучит , как будто вы случайно сохранили ссылку на SqlCommand . Но если вы уверены , что все готово, вы можете попробовать явно установить для каждого .Value значение null и вызвать Clear () в списке параметров. Но на самом деле это всего лишь маскировка того факта, что вы цепляетесь за мертвую команду.

6
ответ дан 18 December 2019 в 06:34
поделиться

Не тестируя это, я могу предложить две вещи, которые могут вам помочь. С SqlParameters вы можете использовать finalize() метод, который освободит ресурсы. Также вы выполняете все свои Sql-команды через блок using? Если да, то после завершения блока using ресурсы должны быть освобождены, и это устранит проблему утечки памяти.

0
ответ дан 18 December 2019 в 06:34
поделиться

Dispose не имеет параметров Dispose, удаляет только его внутренний кеш SqlMetaData ... это нормально, что параметры не удаляются автоматически, потому что вы можете передать что-то, что не должно быть удалено после удаления команды ... + SqlParameter не реализует Dispose, потому что он не содержит неуправляемых ресурсов ....

3
ответ дан 18 December 2019 в 06:34
поделиться

Я использовал этот шаблон в нескольких проектах без каких-либо проблем

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: http://msdn.microsoft.com/en-us/library/5czye81z%28VS.80 % 29.aspx

0
ответ дан 18 December 2019 в 06:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: