首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

PetShop 架構深度剖析(二):數據訪問層的接口隔離與多數據庫適配

     編輯:關於.NET

實體與行為分離:職責單一的踐行

PetShop 將數據庫映射對象劃分為兩類:

  • 數據實體:純屬性類(OrderInfo 等),僅作數據載體,置於 Model 程序集,供 DAL 與 BLL 共同引用
  • 業務邏輯接口:IDAL 組件定義 IOrder 等接口,僅宣告 CRUD 契約,與具體實現完全解耦

這種分離體現「職責分離」與「面向接口編程」:實體變更不影響行為邏輯,新增數據庫類型只需新增實現程序集(SQLServerDAL/OracleDAL),業務層零修改。

OrderInfo 實體類圖
圖 1:OrderInfo 實體類結構
IOrder 接口定義
圖 2:IOrder 接口契約
多數據庫實現類圖
圖 3:SQL Server 與 Oracle 並行實現

無 ORM 環境下的數據訪問封裝策略

PetShop 未引入 ORM,直接使用 SqlCommand/OracleCommand、DataReader 及大量參數字符串常量。為減少重復代碼,引入 DBUtility 模塊封裝 ExecuteNonQuery、ExecuteReader 等靜態方法,差異點(如 Oracle 布爾處理)提供專用 OraBit/OraBool 方法。

OracleHelper 類圖
圖 4:OracleHelper 封裝結構

SQL 管理的演進思考

作者對比了三種方案:

  1. 硬編碼 SQL:分散各層,維護困難,移植痛苦
  2. 存儲過程:邏輯下沉數據庫,但測試難、部署需 DBA 介入、版本控制弱
  3. 專表/XML 存儲 SQL:近似存儲過程調用,避免部署限制,但性能無保障,需配套管理工具

原則:SQL 應盡量收斂於 DAL 具體實現內部,不外洩至上層。

ORM 的 80/20 價值與 PetShop 的抉擇

若引入 NHibernate,CRUD 可簡化為 session.Save(entity),無 SQL/參數煩惱,Dialect 機制天然支持多庫。作者引用帕累托法則:ORM 以 20% 工作量解決 80% CRUD 需求,複雜查詢仍需 SQL 介入。PetShop 選擇手寫 DAL,代價是代碼量激增,但也保留了對底層的完全控制。

抽象工廠簡化版:配置驅動的 DataAccess

標準抽象工廠需實例化具體工廠(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"/>。切換數據庫僅改配置,零代碼變更。

標準抽象工廠類圖
圖 5:標準抽象工廠模式
簡化版工廠類圖
圖 6:PetShop 簡化版工廠模式

重構建議:統一服務定位器

系統中散落大量同樣的「配置+反射」邏輯(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");

這集中了動態創建的配置依賴,利於維護與擴展。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved