Вопрос об утечке памяти в .NET - PullRequest
0 голосов
/ 20 июня 2009

У меня утечка памяти в коде C # У меня есть класс с некоторыми полями SqlCommand внутри него. У меня также есть открытый метод Initialize (), который выделяет эти поля SqlCommands.

Перед распределением я проверяю (в коде Initialize), выполняется ли это в первый раз (не в первый раз, когда вызывается Initialize), и не в первый ли раз Я вызываю Dispose для SqlCommands, и это, кажется, вызывает утечку памяти ....

Теперь важно отметить, что все SqlCommands используют один и тот же SqlConnection и это соединение живы в течение всей жизни программы. Доступ к соединению осуществляется через статическое свойство некоторого статического класса ... (назовем это ConnectionManager)

Есть идеи, в чем может быть проблема? Спасибо!

Ответы [ 2 ]

6 голосов
/ 20 июня 2009

Крембо, рекомендуемый способ использования объектов SqlConnection и SqlCommand находится внутри оператора using, как в этом примере кода из MSDN :

using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();
    // Do work here; connection closed on following line.
}

Вероятно, вам следует избавиться от объекта SqlConnection, как только вы закончили его использовать, хотя может показаться, что это будет медленно, за кадром пул соединений устранит большую часть накладных расходов.

2 голосов
/ 20 июня 2009

Возможно, вам следует опубликовать соответствующий код. Без этого я просто догадываюсь. Тем не менее, вот предположение:

Вы следуете неправильному шаблону здесь. Так как ваш класс поддерживает объекты, которые реализуют IDisposable, ваш класс должен реализовать сам IDisposable. Затем ваши вызывающие пользователи должны быть изменены, чтобы они вызывали метод Dispose вашего класса, когда они закончили с ним:

using System;
using System.Data.SqlClient;

public static class ConnectionManager
{
    private static readonly SqlConnection _connection =
        new SqlConnection("connectionString");
    public static SqlConnection Connection { get { return _connection; } }
}

public class HoldsCommands : IDisposable
{
    private readonly SqlCommand _commandOne = new SqlCommand("Command1");
    private readonly SqlCommand _commandTwo = new SqlCommand("Command2");

    public void DoSomethingWithAConnection()
    {
    }

    public void Dispose()
    {
        if (_commandOne != null)
        {
            try
            {
                _commandOne.Dispose();
            }
            catch (Exception)
            {
            }
        }

        if (_commandTwo != null)
        {
            try
            {
                _commandTwo.Dispose();
            }
            catch (Exception)
            {
            }
        }
    }
}

Ваш абонент тогда позвонит вам так:

using (var commands = new HoldsCommands()) {
    commands.DoSomethingWithAConnection();
}

Как говорит Люк Гирвин, вам, вероятно, не нужен статический класс ConnectionManager, если вы просто пытаетесь сэкономить на соединениях с базой данных. .NET справится с этим за вас.

...