Richard 認為設計框架需具備:**整體把控力、抽象能力、分析能力**。本篇從「以不變應萬變」的 DAL 核心操作出發,推導出通用 IDataContext 介面與基於 Interpreter 模式的 IQuery 查詢對象。
AddSingleDataEntity(T entity)
AddDataEntityList(List list)
UpdateSingleDataEntity(T entity)
UpdateDataEntityList(List list)
DeleteSingleDataEntity(T entity)
DeleteDataEntityList(List list)
GetSingleDataEntity(...)
GetDataEntityList(IQuery query)
命名遵循 .NET Framework Design Guidelines「自解釋性」,但過於冗長。
IDataEntity (空介面,僅作標記)。Common 組件,BLL/DAL 雙向引用不產生循環依賴。where T : class, IDataEntity, new() (滿足 LINQ/EF 實體要求)。
public class DataResult where T : IDataEntity
{
public List EntityList { get; set; } // 新增/修改後的實體 (含自增 PK)
public bool IsSuccess { get; set; }
public Exception Exception { get; set; } // 失敗時攜帶詳細異常
public object CustomData { get; set; } // 擴充欄位 (如影響行數、執行耗時)
}
解決「僅知成敗、不知細節」痛點:呼叫端可依異常類型決定重試/回滾/記錄。
public interface IDataContext
{
// Query
IList Query(IQuery query) where T : class, IDataEntity, new();
IList Query(IQuery query, int pageIndex, int pageSize) where T : class, IDataEntity, new();
// CUD
T Add(T item) where T : class, IDataEntity, new();
IList Add(List items) where T : class, IDataEntity, new();
bool Delete(T item) where T : class, IDataEntity, new();
bool Delete(List items) where T : class, IDataEntity, new();
T Update(T item) where T : class, IDataEntity, new();
IList Update(List items) where T : class, IDataEntity, new();
}
Skip/Take 造成 SQL 注入風險。Query Object = **Interpreter Pattern** 應用:客戶端用領域術語組裝查詢條件,框架負責解釋為 SQL/LINQ/EF 語法樹。
LinqQuery、EFQuery、SqlQuery 實作同一 IQuery,配置切換。
public interface IQuery
{
string UniqueKey { get; } // 查詢唯一標識 (用於緩存鍵)
bool IsReadOnly { get; } // 是否唯讀
// 流暢式建構 API 由具體實現提供 (如 Where, OrderBy, Select)
}
經過層層推演,Richard 確認:**DAL 單純負責「存取與操作資料」**,不包含業務規則、驗證、工作流。上層 (BLL/Repository) 透過 IDataContext 以統一 CRUD + IQuery 與 DAL 交互,達到「以不變應萬變」。
LinqQuery / EFQuery 解析器。IDataContext,提供領域語義 API。