2011-01-26 48 views
5

我希望我的數據訪問層構建得非常模塊化。
因此,我有數據檢索方法,有時直接從業務層調用,有時被其他數據檢索方法調用來創建對象依賴關係。在DAL中處理數據庫連接的最佳方式 - 創建或傳遞?

在DAL中處理數據庫連接的最佳方法是什麼?

a)在每個方法中創建一個新的連接,然後進行處理。
好:易於編寫和使用。
不好:許多連接正在打開和關閉。 (性能?)

b)將連接作爲(可選)參數傳遞。
好的:我可以重複使用一個打開的連接來執行多個命令。
不好:我必須跟蹤連接的所有權(誰必須關閉它?),並且不能使用非常整潔的「using」語句。

c)還有別的嗎? (連接可能是單身人士嗎?)

這是我第一次寫真正的DAL,所以我真的可以使用一些經驗豐富的人幫忙。

編輯:它似乎很重要,它是一個ASP.Net網站項目。

+0

可能是切線,但FWIW,我寧願使用nhibernate,讓它掌握所有這一切。即只使用nhibernate提供的會話對象。 – Biswanath 2011-01-26 21:16:46

回答

5

如果你使用ASP.Net,選項A是你的朋友。

爲每個請求創建一個新的連接,Dispose() - 當請求完成時。確保你使用相同的連接字符串。連接將(默認情況下)保持打開並通過連接池可用。有關連接池的更多信息,請參閱http://msdn.microsoft.com/en-us/library/8xx3tyca.aspx

你幾乎必須在Web服務器上這樣做,所以你沒有併發問題。一切都需要線程安全(你不知道在你的應用程序中執行多少個併發工作線程)。

[編輯追加的代碼示例]

作爲一個例子,這裏就是我會考慮是執行存儲過程的典型方法。這是來自一個自定義的代碼生成器,我寫—手寫代碼可能會看起來有點不同—但它應該足以讓整個點:

public int Exec( int? @iPatientID) 
{ 
    using (SqlConnection conn = new SqlConnection(this.ConnectString)) 
    using (SqlCommand  cmd = conn.CreateCommand()) 
    using (SqlDataAdapter sda = new SqlDataAdapter(cmd)) 
    { 
    cmd.CommandText = STORED_PROCEDURE_NAME ; 
    cmd.CommandType = CommandType.StoredProcedure ; 

    if (this.TimeoutInSeconds.HasValue) 
    { 
     cmd.CommandTimeout = this.TimeoutInSeconds.Value ; 
    } 

    // 
    // 1. @iPatientID 
    // 
    SqlParameter p1 = new SqlParameter(@"@iPatientID" , SqlDbType.Int) ; 
    if (@iPatientID == null) 
    { 
     p1.Value = System.DBNull.Value ; 
    } 
    else 
    { 
     p1.Value = @iPatientID ; 
    } 
    cmd.Parameters.Add(p1) ; 

    // add return code parameter 
    SqlParameter pReturnCode = new SqlParameter() ; 
    pReturnCode.SqlDbType = System.Data.SqlDbType.Int ; 
    pReturnCode.Direction = System.Data.ParameterDirection.ReturnValue ; 
    cmd.Parameters.Add(pReturnCode) ; 

    DataSet ds = new DataSet() ; 

    conn.Open() ; 
    sda.Fill(ds) ; 
    conn.Close() ; 

    this.ResultSet = (ds.Tables.Count > 0 ? ds.Tables[0] : null) ; 
    this.ReturnCode = (int) pReturnCode.Value ; 

    } 

    return this.ReturnCode ; 

} 
+0

是的,它是一個ASP.Net網站。感謝您的鏈接和答案。但我不明白如何傳遞連接可以是一個併發問題? – magnattic 2011-01-26 21:43:37

1

使用所有三個

寫連接,可選參數。如果傳入none(null),則從一些(單獨的,也許是)共享源創建一個連接,以便所有的DAL類創建具有相同確切連接字符串的連接(用於@Nicholas Carey提到的池化)。只有在創建它時纔打開並關閉它。

如果傳入連接,則假定它已經打開並且不關閉它。在更高層次上,當您調用此方法時,可以使用using語句來處理關閉連接。

2

我們使用選項A的變種

我們實際使用實體框架,使我們可以利用LINQ和這樣。實體框架管理自己的連接池,因此創建和刪除上下文很便宜。然後,我們利用依賴注入來管理連接的實際創作,就像這樣:

public class MyDao 
{ 
    IFactory<MyDataContext> _contextFactory; 
    public MyDao(IFactory<MyDataContext> contextFactory) 
    { 
     _contextFactory = contextFactory; 
    } 

    public Foo GetFooById(int fooId) 
    { 
     using (var context = _contextFactory.Get()) 
     { 
      return context.Foos.Single(f => f.FooId == fooId); 
     } 
    } 
} 

這樣一來,如果我們決定,我們想用一個不同的連接字符串,甚至一些更棘手的創造我們的環境,我們可以簡單地在一個位置更改依賴注入綁定,而不必查找每個對new MyDataContext()的調用。

相關問題