Как закрыть DataReader на исключение - PullRequest
5 голосов
/ 06 июля 2011

У меня есть следующий код в некоторых методах моего уровня данных:

StringBuilder sb = new StringBuilder();
SqlCommand s = new SqlCommand(sb.ToString(), conn);
try 
{ 
    SqlDataReader dr = s.ExecuteReader(); 
    while(dr.Read())
      DoSomething(dr);
}
catch (Exception ex)
{ 
    sb.Append(Util.ExceptionRecursive(ex)); 
}

Дело в том, что доктор никогда не закрывается в случае исключения. И когда другой метод пытается получить доступ к другому считывателю данных, он выдает другое исключение, которое говорит что-то вроде «Другой источник данных подключен к базе данных»

Я хочу закрыть свой DataReader в любом случае. Но это:

sb = new StringBuilder();
SqlCommand s = new SqlCommand(sb.ToString(), conn);
SqlDataReader dr;
try 
{
    dr = s.ExecuteReader(); 
    while(dr.Read())
      DoSomething(dr);
}
catch (Exception ex)
{ 
    sb.Append(Util.ExceptionRecursive(ex)); 
}
finally
{
    dr.Close();
}

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

Как мне тогда это сделать?

Ответы [ 3 ]

9 голосов
/ 06 июля 2011

Вы должны использовать оператор using :
. Он генерирует блок finally, чтобы обеспечить постоянное удаление вашего ресурса.

StringBuilder sb = new StringBuilder();
using (SqlCommand s = new SqlCommand(sb.ToString(), conn)) {
    try 
    { 

        using (SqlDataReader dr = s.ExecuteReader()) {
            while(dr.Read())
              DoSomething(dr);
        }

    }
    catch (Exception ex)
    { 
        sb.Append(Util.ExceptionRecursive(ex)); 
    }    
}
3 голосов
/ 06 июля 2011

Лучший способ, вероятно, следующий:

sb = new StringBuilder();
...
using (SqlCommand s = new SqlCommand(sb.ToString(), conn))
using (SqlDataReader dr = s.ExecuteReader())
{
    try
    {
        while(dr.Read())
          DoSomething(dr);
    }
    catch (Exception ex)
    { 
        sb.Append(Util.ExceptionRecursive(ex)); 
    }
}

Однако, если вы ожидаете (или нет) исключения во время выполнения SQL, вы должны поместить код обработки исключений снаружи:

sb = new StringBuilder();
...
try
{
    using (SqlCommand s = new SqlCommand(sb.ToString(), conn))
    using (SqlDataReader dr = s.ExecuteReader())
    {
        while(dr.Read())
          DoSomething(dr);
    }
}
catch (Exception ex)
{ 
    sb.Append(Util.ExceptionRecursive(ex)); 
}
0 голосов
/ 06 июля 2011

Вы можете написать это как:

if(dr!=null) dr.Close();
...