2010-03-02 76 views
3

我幾個月前在MSDN上閱讀過一篇文章,最近開始使用下面的代碼片斷來執行ADO.NET代碼,但是我感覺它可能很糟糕。我是反應還是完全可以接受?ADO.NET - 糟糕的做法?

private void Execute(Action<SqlConnection> action) 
{ 
    SqlConnection conn = null; 
    try { 
     conn = new SqlConnection(ConnectionString); 
     conn.Open(); 
     action.Invoke(conn); 
    } finally { 
     if (conn != null && conn.State == ConnectionState.Open) { 
      try { 
       conn.Close(); 
      } catch { 
      } 
     } 
    } 
} 

public bool GetSomethingById() { 
    SomeThing aSomething = null 
    bool valid = false; 
    Execute(conn => 
    { 
     using (SqlCommand cmd = conn.CreateCommand()) { 
      cmd.CommandText = .... 
      ... 
      SqlDataReader reader = cmd.ExecuteReader(); 
      ... 
      aSomething = new SomeThing(Convert.ToString(reader["aDbField"])); 
     } 
    }); 
    return aSomething; 
} 
+0

除了傳遞給你的連接字符串外,'using'語句還沒有做什麼? – 2010-03-02 20:48:33

回答

0

這是可以接受的。兩年前,我創建了一個類似的方法的SqlUtilities類。如果你喜歡,你可以進一步。

編輯:找不到代碼,但是我輸入了一個小例子(可能有許多語法錯誤;))

SQLUtilities

public delegate T CreateMethod<T> (SqlDataReader reader); 
public static T CreateEntity<T>(string query, CreateMethod<T> createMethod, params SqlParameter[] parameters) { 
    // Open the Sql connection 
    // Create a Sql command with the query/sp and parameters 
    SqlDataReader reader = cmd.ExecuteReader(); 
    return createMethod(reader); 
    // Probably some finally statements or using-closures etc. etc. 
} 

調用代碼

private SomeThing Create(SqlDataReader reader) { 
    SomeThing something = new SomeThing(); 
    something.ID = Convert.ToIn32(reader["ID"]); 
    ... 
    return something; 
} 

public SomeThing GetSomeThingByID (int id) { 
    return SqlUtilities.CreateEntity<SomeThing> ("something_getbyid", Create, ....); 
} 

當然,你可以ü選擇一個lambda表達式而不是Create方法,並且可以輕鬆地創建一個CreateCollection方法並重用現有的Create方法。

但是,如果這是一個新的項目。查看LINQ to實體。比ADO.Net更加容易和靈活。

0

這是用一個非常合理的做法。

通過包裝你的邏輯連接成需要一個Action<SqlConnection>,你幫助防止重複碼和引入誤差的可能性的方法。因爲我們現在可以使用lambda表達式,所以這成爲處理這種情況的一種簡單,安全的方式。

+0

感謝您的意見。 – Echilon 2010-03-02 20:28:56

1

恕我直言,這的確是一個不好的做法,因爲你創建和打開爲您執行每一個語句的新的數據庫連接。

爲什麼這樣做不好:

  • 性能明智的(雖然連接池有助於減少對性能的影響):你應該打開你的連接,執行已被執行的語句,你什麼時候關閉連接不知道下一個語句何時會被執行。

  • 但肯定上下文明智的。我的意思是:你將如何處理交易?你的交易界限在哪裏?您的應用程序層知道什麼時候必須啓動並提交事務,但您無法使用這種工作方式將多個語句跨越到同一個sql事務中。

+0

我想說點什麼來達到這個效果。雖然看起來可以在單個操作中執行多個語句,但我可以看到它被用於爲特定操作生成結果,導致大量不必要的斷開/連接行爲。 – 2010-03-02 18:29:36

+3

他沒有打開和關閉每個語句的數據庫連接。 ADO.NET使用連接池。調用'connection.Close' **不會關閉底層數據庫連接,但會將其返回到連接池以供重用(http://msdn.microsoft.com/zh-cn/library/8xx3tyca%28VS.80 %29.aspx)。 – 2010-03-02 18:31:00

+0

@Darin:這就是我要說的。但是,從語義上講,它仍然是錯誤的。 – 2010-03-02 18:43:54

8

當你可以做到這一點時,這麼做的意義何在?

public SomeThing GetSomethingById(int id) 
{ 
    using (var con = new SqlConnection(ConnectionString)) 
    { 
     con.Open(); 
     using (var cmd = con.CreateCommand()) 
     { 
      // prepare command 
      using (var rdr = cmd.ExecuteReader()) 
      { 
       // read fields 
       return new SomeThing(data); 
      } 
     } 
    } 
} 

您可以通過這樣做來促進代碼重用。

public static void ExecuteToReader(string connectionString, string commandText, IEnumerable<KeyValuePair<string, object>> parameters, Action<IDataReader> action) 
{ 
    using (var con = new SqlConnection(connectionString)) 
    { 
     con.Open(); 
     using (var cmd = con.CreateCommand()) 
     { 
      cmd.CommandText = commandText; 
      foreach (var pair in parameters) 
      { 
       var parameter = cmd.CreateParameter(); 
       parameter.ParameterName = pair.Key; 
       parameter.Value = pair.Value; 
       cmd.Parameters.Add(parameter); 
      } 
      using (var rdr = cmd.ExecuteReader()) 
      { 
       action(rdr); 
      } 
     } 
    }  
} 

你可以使用這樣的:

//At the top create an alias 
using DbParams = Dictionary<string, object>; 

ExecuteToReader(
    connectionString, 
    commandText, 
    new DbParams() { { "key1", 1 }, { "key2", 2 } }), 
    reader => 
    { 
     // ... 
     // No need to dispose 
    } 
) 
+2

+1,完全同意 – 2010-03-02 18:36:39

+0

如果發生異常,會發生什麼情況?我認爲連接會被掛起而沒有關閉會錯誤嗎? – Echilon 2010-03-02 20:30:48

+0

@Echilon - 不,使用聲明將爲您的目的關閉連接。從技術上講,它會保持開放,因爲連接池。 – ChaosPandion 2010-03-02 20:38:51

0

嗯,在我看來你檢查之前通過工作並不意味着它會it.Something做什麼是最好的,良好的編程習慣。看看並找到一個使用它的具體例子和好處。但是如果你正在考慮使用大項目,那麼使用像NHibernate這樣的框架會很好。因爲有很多項目甚至基於它開發的框架,比如http://www.cuyahoga-project.org/