C # - закрытие лучших объектов Sql - PullRequest
11 голосов
/ 30 ноября 2008

Если у вас есть функция C # с Sqlaccess, обязательно ли закрывать все объекты / дескрипторы или все очищается автоматически после выхода из функции

Например:

void DoSqlStuff()
{
    SqlConnection sqlConn = new SqlConnection(...);
    SqlCommand cmd = new SqlCommand(...);
    SqlDataReader sqlData= null;

    sqlConn,Open();
    sqlData = cmd.ExecutReader();


    while(sqlData.Read())
    {
         ...
    }
}

Необязательно, рекомендуется или обязательно закрывать SqlConn и SqlData?

Спасибо.

Ответы [ 8 ]

25 голосов
/ 30 ноября 2008

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

Для этого полезно использование оператора. Он вызовет Dispose () для объекта для вас:

using (SqlConnection cn = new SqlConnection(connectionString))
{   
    SqlCommand cm = new SqlCommand(commandString, cn)
    cn.Open();
    cm.ExecuteNonQuery();       
}
3 голосов
/ 30 ноября 2008

Вам не нужно иметь отдельный оператор использования для SqlDataReader (а также оператор использования для соединения), если только вы не планируете выполнять другие операции с соединением после того, как SqlDataReader полностью прочитает набор строк.

Если вы просто открываете соединение, читаете некоторые данные с помощью устройства чтения, а затем закрываете соединение, тогда достаточно одного оператора using для всего блока кода (окружающего соединение), поскольку сборщик мусора очистит все ресурсы. привязан к соединению, которое удаляется первым оператором using.

В любом случае, вот хорошая статья , которая описывает все это ...

2 голосов
/ 30 ноября 2008

Вы должны закрыть все, прежде чем вернуться из функции. Под открытыми носителями данных подразумеваются открытые курсоры в базе данных, что приводит к увеличению использования памяти. То же самое касается соединений с базой данных.

Неиспользуемые объекты не сразу освобождаются в C #, а только при выполнении сборки мусора, которая не является детерминированной.

1 голос
/ 01 апреля 2010

Будьте осторожны с абсолютами здесь. Многое зависит от того, что вы делаете, и где может лежать неэффективность. На веб-странице, где у каждого пользователя есть отдельный контекст безопасности, у вас может не быть иного выбора, кроме как устанавливать новое соединение SQL с новыми учетными данными безопасности при каждом обращении к странице. Очевидно, лучше, если вы можете использовать пул соединений SQL с общим контекстом безопасности и позволить веб-странице фильтровать результаты, но, возможно, вы не можете.

В более ранних версиях SQL Server, т. Е. (V6.5 или ниже), аутентификация при входе в систему выполнялась SQL Server. Кроме того, SQL был строго ограничен памятью соединений и количеством активных соединений, которые он мог обработать. Так что было бы отличной идеей сбросить соединение, когда оно не используется. Начиная с версии 6.5 большинство людей используют аутентификацию Windows для входа в SQL. Это вызывает много сетевых вызовов между серверами и некоторую задержку. Kerberos Security еще более болтлив, поэтому установка SQL-соединения обходится дорого. По этой причине вам необходимо найти баланс между удержанием соединения открытым в течение всего срока службы приложения WinForms и его открытием и закрытием в каждом вызове метода.

В качестве приблизительного ориентира, если вы думаете, что ваше приложение захочет поговорить с SQL в ближайшие, скажем, 30 секунд. Держите установленное соединение открытым. Если они свернули ваше приложение, не коснулись его в течение определенного периода времени, или вы получили все данные в ОЗУ, и вряд ли им понадобится что-то еще из системы SQL. Закройте соединение.

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

Если вы также не пишете серверный код, небольшая неэффективность памяти может даже не быть замечена. Но 2-10 000 клиентов, плохо использующих ваши серверы безопасности и данных, могут поставить ваш центр обработки данных на колени.

1 голос
/ 30 ноября 2008

Явное удаление в операторе finally - это другой подход, хотя оператор using является гораздо лучшим решением. Он производит немного больше кода, но демонстрирует цель ...

SqlConnection conn = null;
try
{
    //create connection

    SqlCommand cmd = null;
    try
    {
        //create command

        SqlDataReader reader = null;
        try 
        {
            //create reader
        }
        finally
        {
            reader.Dispose();
        }
    }
    finally
    {
        cmd.Dispose();
    }
}
finally 
{
    conn.Dispose();
}
1 голос
/ 30 ноября 2008

Вызов Close на соединении SQL на самом деле не закрывает его, а возвращает его в пул соединений для повторного использования, что повышает производительность.

Кроме того, обычно не рекомендуется явно распоряжаться неуправляемыми ресурсами, когда вы закончите с ними (как можно скорее).

1 голос
/ 30 ноября 2008

Все три класса имеют метод Dispose (). Обязательный является слишком сильным, но определенно настоятельно рекомендуется использовать ключевое слово using, чтобы автоматически вызывался Dispose (). В противном случае ваша программа запускается «тяжело», используя больше системных ресурсов, чем необходимо. И полный сбой, когда вы не используете ключевое слово "new" достаточно для запуска сборщика мусора.

0 голосов
/ 30 ноября 2008

Любой класс, обрабатывающий такие компоненты SQL, как Connections, должен реализовывать интерфейс IDisposable, как указано в рекомендациях по кодированию Microsoft .NET.

Таким образом, вам, вероятно, следует закрыть и утилизировать ваше соединение в вашем методе Dispose.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...