但您有沒有想過這麼做的缺點?缺點在於「過於自由」。由於 GetProduct 方法只將參數限制為 Expression<Func<Product, bool>> 物件,調用時可使用任意形式傳遞。因此外層完全可能傳入目前 LINQ Provider 不支援的表達式樹形式,也可能傳入雖支援但會導致查詢緩慢、影響整體效能的表達式樹。前者在執行時才拋出異常,後者引發的效能問題更難發現。因此我認為,資料存取層不應如此自由,它要做出限制。限制的方式便是使用 Query Object 模式,讓 GetProduct 方法接受一個受限的 Criteria 物件:
public abstract class ProductCriteria
{
internal ProductCriteria(Expression<Func<Product, bool>> query)
{
this.Query = query;
}
public Expression<Func<Product, bool>> Query { get; private set; }
}
class ProductDao
{
public Product GetProduct(ProductCriteria predicate)
{
...
}
}
使用時,我們只提供有限的幾種條件,如:
public class ProductIdEqCriteria : ProductCriteria
{
public ProductIdEqCriteria(int id)
: base(p => p.ProductID == id)
{ }
}
public class ProductViewRangeCriteria : ProductCriteria
{
public ProductViewRangeCriteria(int min, int max)
: base(p => p.ViewCount > min && p.ViewCount < max)
{ }
}
再加上配套的擴充方法用於 And、Or、Not,一切盡在掌握。現在再看看原 Query Object 模式中複雜的實現,您是否會有一種滿足感?