2010-05-13 46 views
1

我正在爲訂購系統項目編寫自定義DAL(VB.NET)。我想解釋一下它是如何編碼的,並且接收一些替代的想法以使得對DAL的編碼更容易/更易讀。 DAL是一個n層(不是n層)應用程序的一部分,每個層都在它自己的程序集/ DLL中。我應該如何提供對此自定義DAL的訪問權限?

DAL由幾個具有特定行爲的類組成。例如,有一個Order類負責檢索和保存訂單。大多數類只有兩個方法,一個是「Get」和一個「Save」,每個方法有多個重載。這些類標記爲「朋友」,並且只對DAL(在它自己的程序集中)可見。

在大多數情況下,DAL返回我稱之爲「數據對象」的內容。此對象是一個只包含數據和驗證的類,位於BLL和DAL都可以讀取的常見程序集中。

爲了向公衆提供DAL,我目前有一個靜態(模塊)類,它有許多共享成員。簡化版本看起來是這樣的:

Public Class DAL 
    Private Sub New 
    End Sub 

    Public Shared Function GetOrder(OrderID as String) as OrderData 

     Dim OrderGetter as New OrderClass 
     Return OrderGetter.GetOrder(OrderID) 

    End Function 

End Class 

Friend Class OrderClass 
    Friend Function GetOrder(OrderID as string) as OrderData 
    End Function 
End Class 

的BLL將要求像這樣的順序:

DAL.GetOrder("123456") 

正如你可以想像,這得到很快累贅。我主要對構建對DAL的訪問感興趣,以便Intellisense非常直觀。就目前而言,DAL類中有太多方法/函數具有相似的名稱。

我有一個想法是把DAL分解成嵌套類:

Public Class DAL 
    Private Sub New 
    End Sub 

    Public Class Orders 
     Private Sub New 
     End Sub 

     Public Shared Function Get(OrderID as string) as OrderData 
     End Function 

    End Class 

End Class 

所以BLL會叫這樣的:

DAL.Orders.Get("12345") 

這清除了一陣,但它留下許多隻有其他類的引用的類,我不喜歡出於某種原因。

沒有訴諸從BLL到DAL傳遞DB特定指令(如where子句),爲DAL提供單一訪問點的最佳或最常見的做法是什麼?

回答

1

你所做的確實是一種改進。你已經做了一系列存儲庫類誰是生活中的工作它返回給你的實體。您也可以將Write/Update/Delete方法放入新的Orders對象中,並將這些東西放在一個地方,這很好。

你最後提出的問題是我們都處理的一個問題。如果你想知道爲什麼LINQ to SQL或LINQ-to-Entities好,這就是爲什麼。它與IQuerable接口有關。使用這兩種技術之一,你的Get方法可以返回一個IQuerable(Order)(看起來可能返回每個訂單對象),然後你可以做LINQ;這實際上將您的業務標準應用於生成的SQL查詢!起初它似乎很神奇,但與IQuerable的本質有關。

如果你是而不是使用這樣的'db'LINQ提供商,那麼你必須贏得你的專業標籤,並以舊式的方式做到這一點:聰明。你仍然想要利用LINQ到對象!哦,是的,你這樣做。您可以添加一個帶有客戶ID並返回IEnumerable(Order)的GetByCustomer(CustomerID As Int),這將根據記錄返回0個記錄或10或50個記錄。(您的Customer對象可能會有一個Orders屬性,它會返回此方法的結果。)但是您不希望爲每個可能情況添加自定義方法。假設您經常想要獲取客戶的最新訂單;你可能想要添加一個GetLatestByCustomer(CustomerID as Int)

但是當您需要時,只需要一次,客戶二階。向DAL對象GetSecondOrderByCustomer()添加方法會很瘋狂,對吧?在這一點上,我們真的混亂了我們的DAL對象。在這種情況下,你可以使用LINQ對你GetByCustomer()方法:

Dim 2ndOrder As Order = (From O in DAL.Orders.GetByCustomer("123") 
          Order By OrderDate).Skip(1).Take(1) 

現在,這是很乾淨,清晰,你不與我們所要考慮的一個非常搞亂DAL專門的請求。請注意,在幕後你會得到給定客戶的每一份訂單!這不應該是世界的終結;我確定你的Orders表有一個CustomerID的索引,對吧?但是,有時候你會得到60個訂單記錄只是爲了獲得第二個記錄。

如果在某個時候你有一個非常瘋狂的查詢需求(獲得兩個日期之間的所有訂單,交付給密爾沃基WI,通過信用卡支付,通過傳真發送),那麼你可能必須提供一個在你的DAL中使用直接的sql選項。如果可以的話,你想要避免這種情況,因爲那樣你就失去了抽象。你可以加Orders.GetBetweenDates(FirstDate As date, SecondDate As date)。是的。 。 。但看到危險?稍後一些開發人員可能會調用它來獲取所有訂單幾年,然後使用LINQ進一步進行過濾。這很容易導致幕後掃描。這些是你必須考慮的事情類型。

你必須謹慎。當你想抽象(這是好的!),你必須做出權衡。 LINQ到SQL等的吸引力是你可以做一個類似於上面例子的LINQ查詢,它只會從db獲得一條記錄!

0

我建議的一個改變是將DAL類基於接口並添加構造函數重載,這將允許您注入依賴項,如ORM組件,連接,命令等......這具有許多優點,最重要的是你可以單獨注入模擬單元測試,並且DAL本身可以被模擬用於消費層測試。

這是多少有些constrived樣品的,但這裏是我可以建議

Public Interface IDal 
    Function GetData(ByVal OrderID As String) As String 
End Interface 

Public Class Dal : Implements IDal 
    Private _connection As IDbConnection 

    Public Sub New() 
     Me.New(IoC.Resolve(Of IDbConnection)) 
    End Sub 

    Friend Sub New(ByVal Connection As IDbConnection) 
     _connection = Connection 
    End Sub 

    Public Function GetData(ByVal OrderID As String) As String Implements IDal.GetData 
     ' Use injected connection and Get the data 
    End Function 
End Class 

牢記模式的真正的基本的例子,這只是爲了說明其可以根據需要修改的模式。請注意他構造函數的Friend範圍。這實際上只意味着被Frield類和程序集調用,比如測試程序集,儘管你可以將它公開並讓消費層注入所有的依賴。

「IoC.Resolve(的IDbConnection)」引入了使用您所選擇的控制反轉(IoC)容器的概念,儘管它並不是真的需要。只要確保你使用默認的具體實現來新建你的依賴項,如果沒有被注入的話。依賴注入和IoC是真正強大的模式,非常適合在DAL中使用。希望這可以幫助。

相關問題