2009-02-14 73 views
15

在我的擴展LinqToSql類中設置DataContext以便於訪問的最佳實踐是什麼?LinqToSql聲明並實例化DataContext最佳實踐?

例如,我有我的dbml「用戶」實體和我想的方法添加到類像這樣:

Partial Public Class User 

    Public Function GetUser(ByVal UserID as Integer) as User 
     'Do Work 
    End Function 

End Class 

爲了訪問我的DataContext我不得不內聲明它方法是這樣的:

Partial Public Class User 

    Public Function GetUser(ByVal UserID as Integer) as User 
     Dim dc as New MyDataContext() 
     Return (From u in dc.Users Where u.ID = UserID).Single() 
    End Function 

End Class 

我想不必爲每一種方法都這樣做。通常情況下(如果我不延長LinqToSql的dbml類)我可能只是這樣做:

Partial Public Class User 
    Private dc as MyDataContext 

    Public Sub New() 
     dc = new MyDataContext() 
    End Sub 

    Public Function GetUser(ByVal UserID as Integer) as User 
     Return (From u in dc.Users Where u.ID = UserID).Single() 
    End Function 

    Public Function GetAllUsers() as IEnumerable(Of User) 
     Return From u in dc.Users 
    End Function 

    'etc... 

End Class 

這將使我訪問每個方法在DataContext,而無需每次都重新申報。但是當然你不能這麼做,因爲dbml已經有了一個構造函數。如果有任何改變,向dbml中添加代碼總會被覆蓋。

任何人有任何關於如何在這裏保存一些多餘的代碼的好主意?

TIA!

回答

13

首先,確保在完成後處置DataContext!他可以是一個沉重的小混蛋(編輯不重要實例化,但重要的是保持在周圍,如果你繼續使用它而不處理);你不希望舊的DataContext在內存中閒逛。

二,DataContext旨在表示單個邏輯事務。例如。您應該在每次要開始新交易時創建一個新交易,並在交易完成時將其清除。所以出於你的目的,那就是大概方法的範圍GetUser。如果您需要將一系列數據庫調用作爲一個組來進行,那麼在刪除它們之前,它們都應該使用相同的DC。

+1

數據上下文本身實際上非常輕量級,儘管它可能引用了很多實體。處理它以釋放實體是一個非常好的主意。如果它是一個重量級的對象,我會更傾向於保持它,所以我不必重新創建它。 – tvanfosson 2009-02-14 17:33:37

+0

@tvanfosson這就是我的意思;編輯,以使這一點更加清晰。 DC可能會帶來很多重量;儘可能快地擺脫它。 – 2009-02-14 17:52:54

0

我認爲或許真正的問題在於User可能不是實例成員調用GetUser的正確位置。

11

由於Rex M said,datacontext旨在爲每個邏輯事務實例化,使用和處理。像這樣的模式有時被稱爲「工作單元」。

這樣做的最常見的方法(我知道)是在using塊中實例化您的datacontext。我沒有用VB在一段時間,但它應該是這個樣子:

Using dc As New MyDataContext() 
    user = (From u in dc.Users Where u.ID = UserID).Single() 
End Using 

這不僅強化了看工作的事務/單元的(通過代碼的物理形狀)但它確保在塊結束時調用DataContext上的Dispose()。

this MSDN page

一般來說,一個DataContext實例設計壽命爲一個「 工作單位」但是你的應用程序定義 這個詞。一個DataContext是 輕量級,並且對於 創建並不昂貴。典型的LINQ to SQL 應用程序在方法範圍創建DataContext 實例或作爲 代表相關 數據庫操作的邏輯集的短命類成員。

0

有幾種不同的方法可以解決這個問題,我認爲這是很好的做法。首先,您可以使用存儲庫模式查詢對象的存儲庫,然後發送到數據庫,檢索對象 - 可能會將其從數據上下文中分離出來,或者根據存儲庫的實現保留數據上下文 - 並返回給你。您的對象的工廠方法將在Repository上,而不是實體本身。您可能會使用反射和泛型來最小化您必須實現的方法的數量並保持代碼乾燥。

另一種方式,以及本意使用LINQtoSQL的方式恕我直言,就是爲您打算執行的每一組數據庫操作創建數據上下文。在這種情況下,數據上下文的創建也發生在實體之外,通常在使用實體的類中,而不是在數據層中。您也可以將方法添加到數據上下文中 - 使您的實際數據上下文抽象並繼承它 - 再次使用反射來執行一些常用的檢索函數,以便您不必重複它們。您可能必須使用像ActiveRecords這樣的數據庫模式,其中ID列始終具有相同的名稱以使其工作。

另一方面,您可以看看使用nHibernate或城堡的ActiveRecord,而不是在您自己的解決方案中複製上述任何一種。

0

如果單獨保留User類並允許IDE處理其創建,則可能會更容易。

通常我更喜歡有一個單獨的類來處理數據檢索。假設您將其稱爲UserDataProvider,並且所有獲取User實例的調用最終都會經過這個類。

UserDataProvider的構造函數可以實例化數據上下文對象的全局實例以供重用。它看起來像這樣(在C#和未經考驗的代碼,所以裸跟我):

public class UserDataProvider 
{ 
    private UserDataContext _data = null; 

    public UserDataProvider() 
    { 
     _data = new UserDataContext(); 
    } 

    public User GetUser(int userID) 
    { 
     return _data.Users.FirstOrDefault(u => u.UserID == userID); 
    } 
} 

或者,你可以放置在一個屬性初始化和訪問該屬性數據上下文用法。

public class UserDataProvider 
{ 
    private UserDataContext _dataContext; 

    private UserDataContext DataContext 
    { 
     get 
     { 
      if (_data == null) 
       _data = new UserDataContext(); 

      return _data; 
     } 
    } 

    public User GetUser(int userID) 
    { 
     return DataContext.Users.FirstOrDefault(u => u.UserID == userID); 
    } 
}