DTO 模式 + 延遲載入 + 實體框架 + ASP.Net MVC + 自動映射器
首先,很抱歉問題很長,但我必須提供一些基本資訊。
我們正在創建一個使用 ASP.net MVC、JQuery 模板、實體框架、WCF 的應用程序,並且我們使用 POCO 作為我們的域層。在我們的應用程序中,有一個 WCF 服務層與 ASP.net MVC 應用程序交換數據,它使用從 WCF 到 MVC 的數據傳輸對象 (DTO)。
此外,在我們的 WCF 服務層中轉換 Domain-TO-DTO 時,應用程序通過使用 AutoMapper 在實體框架中使用延遲載入。
我們的後端架構如下(WCF Services -> Managers -> Repository -> Entity Framework(POCO))
在我們的應用程序中,我們不使用視圖模型,因為我們不想要 MVC 應用程序的另一個映射層,我們只使用 DTO 作為視圖模型。
通常,我們有針對客戶、CustomerLite 等域的 Normal 和 Lite DTO(Lite 對象的屬性比 Normal 少)。
現在我們在使用 DTO 時遇到了一些困難,因為我們的 DTO 結構變得越來越複雜,並且當我們考慮可維護性(使用 DTO 的一般層次結構)時,我們會失去性能。
例如,
我們有客戶視圖頁面和我們的 DTO 層次結構如下
public class CustomerViewDetailsDTO { public CustomerLiteDto Customer{get;set;} public OrderLiteDto Order{get;set;} public AddressLiteDto Address{get;set;} }在這種情況下,我們不希望該視圖的某些 OrderLiteDto 欄位。但是其他一些視圖需要該欄位,因此為了方便它,我們使用該結構。
當涉及到自動映射時,我們映射 CustomerViewDetailsDTO,我們將從延遲載入(實體框架)中獲取額外的數據(特定視圖不需要)。
我的問題:
- 在考慮可維護性的同時,我們可以使用任何機制來提高性能嗎?
- 是否可以將 Automapper 與更多基於地圖視圖的映射功能一起用於相同的 DTO ?
首先不要使用延遲載入,因為它可能會導致 Select N+1 問題或類似問題。
Select N + 1 是一種數據訪問反模式,其中以次優方式訪問數據庫。
換句話說,使用延遲載入而不預先載入集合會導致 Entity Framework 進入數據庫並一次將結果帶回一行。
將 jsRender 用於模板,因為它比 JQuery 模板快得多: Render Bemchmark ,這裡有一個關於如何使用它的好資訊:Reducing JavaScript Code Using jsRender Templates in HTML5 Applications
通常,我們有針對客戶、CustomerLite 等域的 Normal 和 Lite DTO(Lite 對象的屬性比 Normal 少)。
您的正常 DTO 可能是 ViewModel,因為 ViewModel 可能會或可能不會一對一映射到 DTO,並且 ViewModel 通常包含從視圖推回的邏輯,或者幫助根據使用者的響應將數據推回模型。DTO 沒有任何行為,其目的是減少應用程序層之間的呼叫次數。
在考慮可維護性的同時,我們可以使用任何機制來提高性能嗎?
為一個視圖使用一個 ViewModel,您不必擔心可維護性。就個人而言,我通常創建一個作為基礎的抽像類,對於編輯、創建或列表,我繼承該類並添加特定於視圖的屬性。因此,例如,創建視圖不需要 PropertyId(因為有人可以劫持您的文章並發布它),因此只有 Edit 和 List ViewModels 暴露了 PropertyId 屬性。
是否可以將 Automapper 與更多基於地圖視圖的映射功能一起用於相同的 DTO ?
您可以使用 AutoMapper 來定義每張地圖,但問題是,地圖會有多複雜。每個視圖使用一個 ViewModel,您的地圖將易於編寫和維護。我必須指出,不建議在數據訪問程式碼中使用 Automapper,因為:
AutoMapper 的一個缺點是來自域對象的投影仍然強制查詢和載入整個域對象。
來源:自動投影 LINQ 查詢
您可以使用一組目前受限的擴展來加速數據訪問程式碼中的映射:停止在您的數據訪問程式碼中使用 AutoMapper
問候