Зачем использовать оператор using с SqlTransaction? - PullRequest
46 голосов
/ 15 июля 2009

Я столкнулся с некоторыми проблемами, связанными с SqlTransaction, который я использую в своем коде. Во время моего поиска в Google я вижу, как многие люди используют оператор using с SqlTransaction.

В чем выгода и / или разница в использовании этого типа выписки с SqlTransaction?

using (SqlConnection cn = new SqlConnection())
{
     using (SqlTransaction tr = cn.BeginTransaction())
     {
      //some code
      tr.Commit();
     }
}

В настоящее время мой код выглядит так:

SqlConnection cn = new SqlConnection(ConfigurationManager.AppSettings["T3"]);
cn.Open();
SqlTransaction tr = cn.BeginTransaction();

try
{
     //some code
     tr.Commit();
     cn.Close();
}
catch(Exception ex)
{
      tr.Rollback();
      cn.Close();
      throw ex;
}

В чем преимущество одного пути перед другим?

Ответы [ 9 ]

56 голосов
/ 15 июля 2009

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

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

Правильный способ сделать это:

using (SqlConnection cn = new SqlConnection(ConfigurationManager.AppSettings["T3"])) {
    cn.Open();
    using (SqlTransaction tr = cn.BeginTransaction()) {
        //some code
        tr.Commit();
    }
}

Обратите внимание, что если в вашем классе есть экземпляры-члены типов, которые реализуют IDisposable, то ваш класс должен сам реализовать IDisposable и избавиться от этих членов во время своего собственного вызова Dispose().

26 голосов
/ 15 июля 2009

Причиной этого является то, что объект SqlTransaction будет откатываться в своем методе Dispose (), если он не был явно зафиксирован (например, если выдается исключение). Другими словами, он имеет тот же эффект, что и ваш код, только немного чище.

15 голосов
/ 15 июля 2009

По сути, использование делает то же, что и вы, за исключением int блока вместо перехвата всех исключений:

using (SqlConnection cn = new SqlConnection())
{
     using (SqlTransaction tr = cn.BeginTransaction())
     {
      //some code
      tr.Commit();
     }
}

- это то же самое, только намного меньше кода:)

{
    SqlConnection cn = null;
    try
    {
       cn = new SqlConnection();
       {
           SqlTransaction tr = null;
           try
           {
               tr = cn.BeginTransaction())

               //some code
               tr.Commit();
            }
            finally
            {
                if(tr != null && tr is IDisposable)
                {
                    tr.Dispose();
                }
            }
        }
    }
    finally
    {
        if(cn != null && cn is IDisposable)
        {
            cn.Dispose();
        }
    }
}
6 голосов
/ 15 июля 2009

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

В этом случае вы не правильно реализовали шаблон. Что происходит в вашем коде, если вызов tr.RollBack() также вызывает исключение?

4 голосов
/ 15 июля 2009

Оператор using закрывает и удаляет ваше соединение и транзакцию для вас. Это то же самое, что иметь блок finally на вашем try / catch, который делает удаление.

Вы могли бы также немного сжать используемые блоки ...

using (SqlConnection cn = new SqlConnection())
using (SqlTransaction tr = cn.BeginTransaction())     
{
      //some code
      tr.Commit();
}

, что было бы примерно так же, как:

SqlConnection cn = null;
SqlTransaction tr = null;
try
{
    cn = new SqlConnection());
    tr = cn.BeginTransaction());

    //some code
    tr.Commit();
}
finally
{
    if (cn != null)
        cn.Dispose();
    if (tr != null)    
        tr.Dispose();
}
3 голосов
/ 15 июля 2009

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

2 голосов
/ 06 апреля 2012

В дополнение ко всему этому, он укрепляет ваш код. Разве 7 строк кода не выглядят лучше, чем 14 строк? Я выдыхаю знак облегчения каждый раз, когда вижу блок использования. Это похоже на маленькую капельку тумана, которая выходит из этой радостной вонючей вещи. Ммм, я хороший блок эффективного кода. Посмотрите, как хорошо я управляю памятью и как я радуюсь глазу.

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

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

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

Оператор Using является сокращением для правильной обработки ресурса. Более подробную информацию вы можете найти в статье MSDN об использовании оператора

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