2012-02-24 3 views
1

Не большое дело, но для аккуратности есть ли способ «создать и открыть» SqlConnection?Любой способ избежать развёртывания при открытии SqlDataReader?

я наивно написал этот код:

using (var strConnection = new SqlConnection(sourceConnection)) 
using (var strCommand = new SqlCommand(query, strConnection)) 
using (var reader = strCommand.ExecuteReader()) 
{ 
    ... 
} 

Что, конечно, не будет работать на линии 3, так как соединение не открыто.
Есть ли опрятный способ избежать этого гнездования, которое открывает соединение?

using (var strConnection = new SqlConnection(sourceConnection)) 
{ 
    strConnection.Open(); 
    using (var strCommand = new SqlCommand(query, strConnection)) 
    using (var reader = strCommand.ExecuteReader()) 
    { 
     ... 
    } 
} 
+0

Вам действительно нужно соединение только для одной команды? Возможно, вы должны держать соединение открытым в течение более длительного времени. – svick

ответ

1

Хороший вопрос, моя идея разгибания метод SqlConnection.

Проверьте это:

public static class SqlExtensions { 
    public static SqlConnection OpenAndReturn(this SqlConnection con) { 
     try { 
      con.Open(); 
      return con; 
     } catch { 
      if(con != null) 
       con.Dispose(); 
      throw; 
     } 
    } 
} 

Использование:

using(var strConnection = new SqlConnection("CONNECTION").OpenAndReturn()) 
using(var strCommand = new SqlCommand("QUERY", strConnection)) 
using(var reader = strCommand.ExecuteReader()) { 
    //...  
} 
+0

хорошее мышление! Мне нравится этот, красивый и простой. – Coxy

+2

Использование этого подхода не рекомендуется: если в «OpenAndReturn» возникает исключение, соединение не будет удалено. т.е. в этом случае блок 'using' начинает защищать объект, когда он возвращается из' OpenAndReturn', а не тогда, когда он создается 'new SqlConnection (...)'. (Конечно, вы можете усилить метод расширения с помощью собственной 'try ... catch ... Dispose', чтобы компенсировать это.) – LukeH

+0

Является ли это приемлемым ответом? – Malmi

1

А что-то вроде этого:

class SqlHelper : IDisposable 
{ 
    public SqlHelper(string connectionString, string query) { ... } 

    public SqlConnection Connection { get; set; } 
    public SqlCommand Command { get; set; } 

    // SQL querying logic here 
    public void Execute() { ... } 

    /** IDisposable implementation **/ 
} 

и в коде

using (SqlHelper sql = new SqlHelper(sourceConnection, query)) 
{ 
    var reader = sql.Execute(); 
    ... 
} 
+0

И как вы 'Dispose()' читателя? – svick

+0

@svick Это хороший момент, возможно, вы можете передать блок в 'use' в качестве делегата, чтобы читатель мог быть удален из помощника. – Guillaume

Смежные вопросы