C # IDisposable Использование: лучшая практика - PullRequest
7 голосов
/ 21 октября 2011

Я уже некоторое время оборачиваю свои объекты OracleConnection и OracleCommand в операторы USING, однако после запуска анализатора кода я обнаружил, что 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...
        }
    }
}

Ответы [ 7 ]

7 голосов
/ 21 октября 2011

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

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 голос
/ 21 октября 2011
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... 
    } 
} 
1 голос
/ 21 октября 2011

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

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

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

0 голосов
/ 21 октября 2011

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

0 голосов
/ 21 октября 2011

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

0 голосов
/ 21 октября 2011

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

0 голосов
/ 21 октября 2011

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

Вместо этого вы должны сделать это следующим образом

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();
...