C # IDisposable Использование: лучшая практика

#c# #coding-style #idisposable #using

#c# #стиль кодирования #idisposable #использование

Вопрос:

Я уже некоторое время обертываю свои объекты OracleConnection и OracleCommand в операторах USING, однако после запуска code analyzer я обнаружил, что OracleParameter также реализует IDisposable . Правильный ли следующий код? Есть ли лучший метод для удобства чтения или структуры? На первый взгляд кажется, что он просто загроможден операторами USING:

 using (OracleConnection conn = new OracleConnection(connectionstring))
{
    conn.Open();
    using (OracleCommand cmd = new OracleCommand(sql, conn))
    {
        cmd.BindByName = true;

        using (OracleParameter param1 = new OracleParameter("p1", OracleDbType.Int32, System.Data.ParameterDirection.Input))
        {
            param1.Value = int.Parse(value1);
            cmd.Parameters.Add(param1);
        }

        using (OracleParameter param2 = new OracleParameter("p2", OracleDbType.Varchar2, System.Data.ParameterDirection.Input))
        {
            param2.Value = value2;
            cmd.Parameters.Add(param2);
        }

        using (OracleDataReader dr = cmd.ExecuteReader())
        {
            // loop data here...
        }
    }
}
 

Ответ №1:

Вы хотите удалить параметры только в самом конце их использования, в том числе во время запроса (и, возможно, при чтении результатов):

 using (OracleConnection conn = new OracleConnection(connectionstring))
{
    conn.Open();
    using (OracleCommand cmd = new OracleCommand(sql, conn))
    {
        cmd.BindByName = true;

        using (OracleParameter param1 = new OracleParameter("p1", OracleDbType.Int32, System.Data.ParameterDirection.Input))
        using (OracleParameter param2 = new OracleParameter("p2", OracleDbType.Varchar2, System.Data.ParameterDirection.Input))
        {
            param1.Value = int.Parse(value1);
            cmd.Parameters.Add(param1);
            param2.Value = value2;
            cmd.Parameters.Add(param2);

            using (OracleDataReader dr = cmd.ExecuteReader())
            {
                // loop data here...
            }
        }
    }
}
 

Обратите внимание, что вы можете поместить несколько using операторов подряд. Это потому, что, как if и утверждение,

  1. using Оператор считается простым оператором (даже с блоком); и
  2. using Оператор может содержать либо блок, либо оператор под ним.

Комментарии:

1. Хотя было много похожих ответов, я оценил, что вы предоставили как примеры, так и комментарии.

2. Спасибо! Рад, что смог помочь. 🙂

Ответ №2:

 using (OracleConnection conn = new OracleConnection(connectionstring)) 
using (OracleCommand cmd = new OracleCommand(sql, conn)) 
using (OracleParameter param1 = new OracleParameter("p1", OracleDbType.Int32,
       System.Data.ParameterDirection.Input)) 
using (OracleParameter param2 = new OracleParameter("p2", OracleDbType.Varchar2,
       System.Data.ParameterDirection.Input)) 
}
    conn.Open(); 
    cmd.BindByName = true; 

    param1.Value = int.Parse(value1); 
    cmd.Parameters.Add(param1); 

    param2.Value = value2; 
    cmd.Parameters.Add(param2); 

    using (OracleDataReader dr = cmd.ExecuteReader()) 
    { 
        // loop data here... 
    } 
} 
 

Ответ №3:

Я не уверен, что это будет работать должным образом. Учтите, что в конце использования оба параметра должны быть удалены. Тот факт, что ваш cmd.Parameters объект все еще содержит ссылку на них, не исключает того, что может происходить в методе OracleParameter Dispose. Для всех интенсивных целей разработчик этого конкретного объекта может очищать поля, которые вы OracleCommand ожидаете заполнить.

Здесь есть некоторая опасность. Если вы абсолютно уверены, что хотите правильно распорядиться своим OracleParameters , я предлагаю вам избавиться от них после OracleDataReader использования.

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

Ответ №4:

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

Ответ №5:

Согласно MSDN, вам нужно использовать только using Connection DataReader объекты for и . Я никогда не видел using (или .Dispose() ) не использовал с ADO.NET объекты параметров. Если бы это было необходимо или даже желательно, я думаю, что это появилось бы уже некоторое время в течение последних 10 лет.

Комментарии:

1. MSDN говорит об объектах, предоставляемых BCL. Реализация Oracle этих параметров вполне может потребовать удаления параметров. Зачем им реализовывать IDisposable, если они не предназначены для удаления?

2. Или они вполне могут и не быть. Я никогда не видел ни одного ADO.NET код (для реализации Oracle или кого-либо еще), который либо вызывал Dispose() для объекта параметра, либо помещал его в using блок. Опять же, если бы удаление параметров было необходимо, это уже давно подняло бы голову.

3. Итак, ваш совет: даже если объект реализует IDisposble, не удаляйте его, если не известно, что это проблема? Звучит как плохой совет для меня.

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

Ответ №6:

Нет, это неверно, потому что вы удаляете параметры еще до их использования.

Вместо этого вы должны сделать это так

 OracleParameter param1 = new OracleParameter("p1", OracleDbType.Int32, System.Data.ParameterDirection.Input);

param1.Value = int.Parse(value1);
cmd.Parameters.Add(param1);


OracleParameter param2 = new OracleParameter("p2", OracleDbType.Varchar2, System.Data.ParameterDirection.Input);

param2.Value = value2;
cmd.Parameters.Add(param2);


using (OracleDataReader dr = cmd.ExecuteReader())
{
  // loop data here...
}

param1.dispose();
param2.dispose();
 

Ответ №7:

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