2011年11月17日 星期四

LINQ動態查詢 使用(PredicateBuilder)

官網抵佳:PredicateBuilder
需使用套件: LINQKit
套件及範例下載位址:在LINQKit頁面的最下方

官網範例如下
IQueryable<SearchProducts>(params string[] keywords)
{
 var predicate = PredicateBuilder.False();
 foreach (string keyword in keywords)
 {
  string temp = keyword; // 很重要!! 一定要加
  predicate = predicate.Or (p => p.Description.Contains (temp));
 }
 return dataContext.Products.Where (predicate);
}

--------------------------------
下面是運作說明

步驟1:建立PredicateBuilder物件(我們需要使用此物建來作查詢條件的串接)
var predicate = PredicateBuilder.False();
步驟2:迴圈加入查詢條件
foreach(string keyword in keywords)
{
  string temp = keyword; // 避免參考到相同變數位址,所以需加上此行
  predicate = predicate.Or (p =< p.Description.Contains (temp));
}
步驟3:執行查詢
dataContext.Products.Where (predicate);
or 使用 dataContext.Products.Where(predicate.Compile());

-----------------完成!!------------------

接下來是運作原理的說明

當只執行
var predicate = PredicateBuilder.False();
dataContext.Products.Where (predicate.Compile());
這段描述看起來會像是 dataContext.Products.Where (src => false);

若是執行
var predicate = PredicateBuilder.False();
predicate = predicate.Or (src => src.keyword == "123");
dataContext.Products.Where (predicate.Compile());
這段描述看起來會像是 dataContext.Products.Where (src => false || src.keyword == "123");

若是執行
var predicate = PredicateBuilder.False();
predicate = predicate.Or (src => src.keyword == "123");
predicate = predicate.And(src => src.id == 5);
dataContext.Products.Where (predicate.Compile());
這段描述看起來會像是 dataContext.Products.Where (src => false || src.keyword == "123" && src.id == 5);

由此可知條件是串接起來的
因此預設選擇PredicateBuilder.False或PredicateBuilder.True就很重要了

舉個例子,如果希望找出keyword1或keyword2,兩個關鍵字只要一個成立即可的結果

範例會像這樣
var predicate = PredicateBuilder.False();
predicate = predicate.Or (src => src.keyword == "123");
predicate = predicate.Or (src => src.keyword == "456");
dataContext.Products.Where (predicate.Compile());
這段描述看起來會像是 dataContext.Products.Where (src => false || src.keyword == "123" ||src.keyword == "456"); //這是正確的結果
若預設選擇PredicateBuilder.True();
這段描述看起來會像是dataContext.Products.Where (src => true || src.keyword == "123" ||src.keyword == "456");
這樣一來查詢的結果永遠會是true,而導致錯誤了

在一個例子,如果希望找出keyword1且keyword2,兩個關鍵字都要成立的結果
範例應該像這樣
var predicate = PredicateBuilder.True();
predicate = predicate.And (src => src.keyword == "123");
predicate = predicate.And (src => src.keyword == "456");
dataContext.Products.Where (predicate.Compile());
這段描述看起來會像是 dataContext.Products.Where (src => true && src.keyword == "123" && src.keyword == "456"); //這是正確的結果
若預設選擇PredicateBuilder.False();
這段描述看起來會像是 dataContext.Products.Where (src => false && src.keyword == "123" && src.keyword == "456");
這樣一來查詢的結果就永遠會是false,而導致錯誤了







沒有留言:

張貼留言