PetShop 將數據庫映射對象劃分為兩類:
OrderInfo 等),僅作數據載體,置於 Model 程序集,供 DAL 與 BLL 共同引用IDAL 組件定義 IOrder 等接口,僅宣告 CRUD 契約,與具體實現完全解耦這種分離體現「職責分離」與「面向接口編程」:實體變更不影響行為邏輯,新增數據庫類型只需新增實現程序集(SQLServerDAL/OracleDAL),業務層零修改。
PetShop 未引入 ORM,直接使用 SqlCommand/OracleCommand、DataReader 及大量參數字符串常量。為減少重復代碼,引入 DBUtility 模塊封裝 ExecuteNonQuery、ExecuteReader 等靜態方法,差異點(如 Oracle 布爾處理)提供專用 OraBit/OraBool 方法。
作者對比了三種方案:
原則:SQL 應盡量收斂於 DAL 具體實現內部,不外洩至上層。
若引入 NHibernate,CRUD 可簡化為 session.Save(entity),無 SQL/參數煩惱,Dialect 機制天然支持多庫。作者引用帕累托法則:ORM 以 20% 工作量解決 80% CRUD 需求,複雜查詢仍需 SQL 介入。PetShop 選擇手寫 DAL,代價是代碼量激增,但也保留了對底層的完全控制。
標準抽象工廠需實例化具體工廠(new SQLServerFactory()),仍產生編譯期依賴。PetShop 採用「帶簡單工廠特質的抽象工廠」:
DataAccess 為 sealed 靜態類WebDAL/OrdersDAL 指向實現程序集Assembly.Load(orderPath).CreateInstance(orderPath + ".Order")public sealed class DataAccess {
private static readonly string orderPath = ConfigurationManager.AppSettings["OrdersDAL"];
public static IOrder CreateOrder() {
return (IOrder)Assembly.Load(orderPath).CreateInstance(orderPath + ".Order");
}
}
配置範例:<add key="OrdersDAL" value="PetShop.SQLServerDAL"/>。切換數據庫僅改配置,零代碼變更。
系統中散落大量同樣的「配置+反射」邏輯(IBLLStrategy、CacheDependencyFactory 等)。作者提議提煉 ServiceLocator 統一管理命名空間鍵值,簡化 DataAccess 等調用端:
public static class ServiceLocator {
private static readonly string orderPath = ConfigurationManager.AppSettings["OrdersDAL"];
public static object LocateDALOrderObject(string className) {
return Assembly.Load(orderPath).CreateInstance(orderPath + "." + className);
}
}
// DataAccess 簡化為
public static IOrder CreateOrder() => (IOrder)ServiceLocator.LocateDALOrderObject("Order");
這集中了動態創建的配置依賴,利於維護與擴展。