Удаление SqlConnection при возникновении исключения

Меня интересует следующий шаблон кода:

    static SqlConnection getcon()
    {
        SqlConnection con = new SqlConnection("data source=foobar..");
        con.Open();

        // is con Disposed automatically or will it leak and live 
        // forever when exception is thrown?

        throw new Exception("exception");
        return con;
    }

    static void Main(string[] args)
    {
        try 
        {
            using (var scope = new TransactionScope())
            using (var con = getcon())
            using (var cmd = new SqlCommand("UPDATE SomeTable SET Column1 = 'test'", con))
            {                   
                cmd.ExecuteNonQuery();

                scope.Complete();
            }
        }
        catch     
        {
        }
    }

Это безопасный способ использования SqlConnection (получение соединения с помощью метода getcon())? Будет ли он удален после выхода из функции при возникновении исключения или будет жить вечно?

Цель, почему мне нужен этот GetCon() метод, - сократить код и заключить создание и открытие соединения в одну строку (using (var con = getcon()) ..)


person Jaska    schedule 05.08.2013    source источник
comment
Я отредактировал ваше название. См. Должны ли вопросы включать «теги» в свои заголовки?, где нет единого мнения, не следует.   -  person John Saunders    schedule 06.08.2013
comment
Ok! Но удаляется ли соединение, даже если исключение возникает в строке using, а не в фигурных скобках {}?   -  person Jaska    schedule 06.08.2013
comment
Пройти через все эти проблемы (и, возможно, с побочными эффектами и ошибками), чтобы просто избежать ввода одной строки кода (conn.Open()), кажется очень ошибочной и преждевременной оптимизацией - не делайте этого. Просто оно того не стоит.   -  person marc_s    schedule 06.08.2013


Ответы (3)


is con Disposed automatically or will it leak and live orever when exception is thrown?

throw new Exception("exception");
return con;//your code

Фактически return con; линия недоступна. Другими словами, здесь он никогда не будет выполняться. вы не возвращаете con метод, на самом деле выходит, бросая Exception. так что ваше соединение не будет очищено here.

Когда метод завершается (в порядке исключения), локальная переменная выходит за пределы Scope, и у вас нет управляемых ссылок на нее, поэтому очевидно, что ваш con подчиняется Garbage Collection.

will it leak and live orever when exception is thrown?

Ответ: нет, сборщик мусора позаботится об освобождении памяти, используемой Connection, и ваше соединение будет закрыто, когда Dispose(true) обычно вызывается из Finalizer.

Изменить

Предположим, что ваш метод get con не генерирует никаких исключений и возвращает Connection, а Exception выбрасывается, как показано ниже.

using (var scope = new TransactionScope())
using (var con = getcon())
using (var cmd = new SqlCommand("UPDATE SomeTable SET Column1 = 'test'", con))
{
    throw new Exception("Oops");//Throw excception somewhere here             
    cmd.ExecuteNonQuery();
    scope.Complete();
}

Приведенный выше код гарантирует очистку при возникновении исключения, поскольку вы заключили con в using оператор.

Надеюсь это поможет

person Sriram Sakthivel    schedule 05.08.2013

Как вы написали метод getcon (я предполагаю, что вы сделали это специально для проверки чего-то), con будет освобождено в момент возникновения исключения. Поскольку `return con; ' находится после генерируемого исключения, оно никогда не будет возвращено в вызывающий код и будет освобождено, как только getcon завершит работу (для выхода за пределы области видимости).

person jaadooviewer    schedule 05.08.2013

Я думаю, что ответ jaadooviewer правильный, но похоже, что вы могли бы полностью избежать вопроса, используя блок try / catch в методе getcon.

try
{
    SQLConnection con = new SQLConnection("...");
    con.Open();
    if (/*condition*/)
        throw new Exception("Exception Condition Satisfied");
}
catch (Exception ex)
{
    con.Dispose();
    throw ex;
}
return con;
person IllusiveBrian    schedule 05.08.2013
comment
Основной вопрос здесь заключается в том, расширяет ли использование -block свои щупальца внутри метода getcon() или нет. - person Jaska; 06.08.2013
comment
@Jaska - Да. getcon() вызывается внутри вашего блока using, так сказать, внутри блока. - person Tim; 06.08.2013
comment
Вероятно, вы захотите сделать catch (Execption) в сочетании с throw;, чтобы не потерять трассировку стека. (также Dispose() неявно вызывает Close() для SqlConnection, поэтому вам не нужно вызывать его в блоке catch) - person Scott Chamberlain; 06.08.2013
comment
Я не совсем понимаю, что вы имеете в виду под первым комментарием. Спасибо за разъяснения по второму вопросу. - person IllusiveBrian; 06.08.2013