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

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

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 ответов


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

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. A using оператор считается простым оператором (даже с блоком); и
  2. A using оператор может принимать либо блок, либо оператор нижний.

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

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

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


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... 
    } 
} 

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

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

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

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


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


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