c # sql что распоряжаться - PullRequest
5 голосов
/ 21 июля 2009

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

Нужно ли утилизировать SqlDataReader, поскольку он находится в блоке try catch?

Нужно ли запускать как cmd.Dispose, так и cmd.Connection.Close или один выводит другой?

Будет ли сборщик мусора в конечном итоге утилизировать все эти объекты в любом случае (возможно, не достаточно своевременно) или эти объекты косвенно требуют удаления, возможно, из-за использования неуправляемого кода?

public void GetData(string studentID)
    {
        SqlCommand cmd = new SqlCommand("sp_stored_proc", 
                new SqlConnection(Settings.Default.connectionString)) 
                { CommandType = CommandType.StoredProcedure };
        try
        {
            cmd.Connection.Open();
            cmd.Parameters.AddWithValue("@student_id", studentID);
            SqlDataReader dr = cmd.ExecuteReader();

         //do something with the data

            if (dr != null)
                dr.Dispose();
        }
        catch
        {
            //error handling
        }
        finally
        {
            if (cmd != null)
            {
                cmd.Dispose();
                cmd.Connection.Close();
            }

        }

    }

Ответы [ 6 ]

17 голосов
/ 21 июля 2009

Вы должны утилизировать считыватель данных и команду. Нет необходимости отдельно закрывать соединение, если вы располагаете команду. В идеале вы должны сделать оба, используя using блок:

using (SqlCommand cmd = new...)
{
    // do stuff
    using (SqlDataReader dr = cmd.ExecuteReader())
    {
        // do stuff
    }
}

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

3 голосов
/ 21 июля 2009

Если вы используете что-то вроде этого:

public void GetData(string studentID)
{
    using (SqlConnection connection = new SqlConnection(Settings.Default.connectionString))
    {
        connection.Open();

        using (SqlCommand command = connection.CreateCommand())
        {
            command.CommandType = CommandType.StoredProcedure;
            command.CommandText = "sp_stored_proc";
            command.Parameters.AddWithValue("@student_id", studentID);

            using (SqlDataReader dataReader = command.ExecuteReader())
            {
                // do something with the data
            }
        }
    }
}

тогда все ваши одноразовые предметы будут утилизированы правильно. Вызов Dispose () для объектов SqlConnection, SqlCommand и SqlDataReader (что делает блок using при выходе) закрывает их правильно.

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

Недостатком этого подхода является то, что если вам нужна обработка ошибок с использованием try / catch, вы должны либо обернуть ее вокруг всего тела метода, либо использовать несколько из них для обработки ошибок соединения, отличных от ошибок чтения и т. Д. .

3 голосов
/ 21 июля 2009

Нужно ли утилизировать SqlDataReader так как это в пределах улова попытки блок

- Да, так как находящийся внутри try-улова не вызовет метод dispose.

Нужно ли запускать как cmd.Dispose, так и cmd.Connection.Close или одно выводит другое?

- Да, вам нужно запустить оба. Вызов Cmd.dispose не закрывает соединение.

Метод dispose предназначен для использования программистом для очистки ресурсов, которые либо непосредственно не управляются сборщиком мусора, либо должны быть очищены после того, как программа будет выполнена, используя их для освобождения места. Технически, можно настроить программу так, чтобы GC обрабатывал ее утилизацию, но я бы не стал делать такое предположение, тем более что программист, пишущий класс, предоставил вам метод dispose. Помещение команды в оператор using, вероятно, является самым простым путем, потому что вы знаете, что он будет удален, когда код покинет пространство объявления.

using (var connection  = new Connection ())
{
   using (var cmd = new Command())
   {



   }
}
2 голосов
/ 21 июля 2009

Лично, если у чего-то есть метод утилизации, то в любом случае его стоит использовать, так как он предотвратит протечки памяти.

1 голос
/ 21 июля 2009

Короче говоря; если он реализует IDisposable, вы должны позвонить Dispose.

Даже если вы используете Reflector, чтобы выяснить, что Dispose в одном объекте вызывает Dispose для другого объекта, я все равно рекомендовал бы вызывать Dispose для обоих, поскольку это внутренние детали реализации, которые могут изменить в некоторых будущих выпусках, так что не стоит полагаться на то, что это всегда так.

Итак, Dispose все, что есть IDisposable.

0 голосов
/ 21 июля 2009

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

вы можете использовать ключевое слово "using", чтобы избавиться от него, но это не очень хорошая идея

на самом деле ключевое слово «using» предназначено для автоматического удаления объекта. другими словами, объект должен достигнуть распоряжения методом

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