LINQ to SQL Web 應用程序最佳實踐
在我建構 Web 應用程序的經驗中,我一直使用 n 層方法。從數據庫獲取數據並填充對象的 DAL,從 DAL 獲取對象並執行它們所需的任何業務邏輯的 BLL,以及從 BLL 獲取它的顯示數據的網站。我最近開始學習 LINQ,大多數範例顯示了直接來自 Web 應用程式碼隱藏的查詢(我可能只看到過簡化的範例)。在 n 層架構中,這總是被視為大忌。
我有點不確定如何建構一個新的 Web 應用程序。我一直在 VS2008 中使用伺服器資源管理器和 dbml 設計器來創建 dbml 和對象關係。我似乎有點不清楚 dbml 是否會被視為 DAL 層,網站是否應該呼叫 BLL 中的方法,然後會執行 LINQ 查詢等。
有哪些通用架構最佳實踐或創建方法使用 LINQ to SQL 的 Web 應用程序解決方案?
恐怕你確實見過過於簡化的例子。LINQ to SQL (System.Data.Linq) 是您的 DAL 層。L2S 生成的類是您的域(但不要與域驅動設計混淆)。最重要的是,您仍然可以編寫業務層。
我總是試圖防止將 LINQ to SQL 洩漏
DataContext到表示層(您的 Web 應用程序)中。所以它不應該能夠創建或送出一個DataContext. 您也不應該將IQueryable<T>對象返回到表示層。IMO 業務層應該完全控制DataContext(工作單元)的生命週期和 SQL 查詢的形狀。然而,有幾種口味。有些人傾向於放鬆這些限制。其他人甚至走得更遠。這取決於您自己的口味和應用程序的大小。應用程序越大,添加抽象層就越合理。
當不允許
IQueryables 和其他與數據相關的東西離開業務層時,您最終會遇到一些有趣的挑戰。例如,表示層必須指示業務層如何對結果進行排序。雖然您可以讓表示層自己對結果進行排序,但這意味著您必須從表示層的數據庫和頁面中獲取所有數據,這會導致系統性能非常差。這個問題有幾種解決方案。在所有情況下,您都需要通知業務層如何為您排序結果。當您搜尋LINQ 動態排序時,可以在 SO 上找到解決方案。我自己在這裡寫了這樣的解決方案。不允許
IQueryables 離開你的 BL 會帶來的另一個挑戰是域對象通常也不能離開你的 BL。大多數 LINQ to SQL 域對象將包含延遲載入的屬性(例如,其他域對象的集合)。但是,當DataContext業務層控制它時,它會在您將結果返回到表示層之前被處理掉。當表示訪問一個延遲載入的屬性時,將發生異常,因為該屬性DataContext已經被釋放。當您DataContext在業務層中配置時,此行為當然是“設計使然”。允許表示層獲得延遲載入的屬性意味著 BL 失去對發送到數據庫的查詢的控制,從而失去對性能的控制。要解決此問題,您應該將數據傳輸對象 (DTO) 從 BL 返回到表示層。DTO 將只包含 data 而沒有internal
DataContext,也沒有延遲載入的屬性。DTO 可以針對手頭的實際請求進行特殊格式化。DTO 本身當然會導致編碼成本,因此系統的大小和性能需求必須證明它是合理的。為了讓自己更容易,我傾向於將靜態投影方法放在 DTO 上。雖然這不符合關注點分離原則,但我發現它是一個非常實用的解決方案。例如查看此 CustomerDTO:public class CustomerDTO { public int CustomerId { get; set; } public string Name { get; set; } // City is flatterned from Address.City. public string City { get; set; } internal static IQueryable<CustomerDTO> AsDTO(IQueryable<Customer> customers) { return from customer in customers select new CustomerDTO() { CustomerId = customer.Id, Name = customer.Name, City = customer.Address.City }; } }此 DTO 定義了一個內部
AsDTO方法,該方法能夠將Customer域對象集合轉換為CustomerDTODTO 集合。這使得域對像到 DTO 的轉換更加容易。例如看這個 BL 方法:public static CustomerDTO[] GetCustomersByCountry(string country) { using (var db = ContextFactory.CreateContext()) { IQueryable<Customer> customers = (from customer in db.Customers where customer.Address.Country == country orderby customer.Name, customer.Id); return CustomerDTO.AsDTO(customers).ToArray(); } }這種方法的好處是,當您查看 SQL 查詢時,您會看到只有客戶 ID、姓名和地址表的城市將從數據庫中檢索到。這是因為該
AsDTO方法可以將一種方法轉換IQueryable為另一種方法,從而允許 LINQ to SQL 執行數據庫中的全部操作。我希望這能給你一些關於你能做什麼的想法。當然,這是我對這個主題的看法,也是我發現在我的情況下實用的東西。