Linq之動態查詢
Linq之動態查詢。
最近寫Linq碰到一個問題,
就是如果要寫一個查詢系統,這個系統裡面有很多TextBox可以填,
然後撈出符合各個欄位的資料。
在SQL查詢的時候還滿方便的,用字串連連連就可以了,
( 也就是sqlStr += "or name like '%sanc%' " )
那在Linq的話呢,就完全沒有辦法可以用連連連的方法QQ
後來和G神禱告後,G神告訴我目前有三種方法可以處理。
第一是出自MS的Linq Dynamic Query Library
但聽說一堆問題,就懶得去試了。
第二是自己寫運算式樹,也就是建立QueryBuilder
好吧,我有空會再找時間研究看看QQ
第三則是由有名的C# In a Nutshell作者寫的一個Library
( 其實滿想讀他寫的書的,但是全英文....光看這篇,就懶了= = )
總之,最後用了第三個方案,因為真的很方便,也很直覺。
要擴充或是移除,都很方便。
他給的第一個範例是這樣,這個範例沒用到什麼技巧,
反正直接就可以用了。
IQueryable SearchProducts (params string[] keywords) { IQueryable query = dataContext.Products; foreach (string keyword in keywords) { string temp = keyword; query = query.Where (p => p.Description.Contains (temp)); } return query; }這個的功能很簡單,假設你送進去,"可樂"、"暢快",
他就會把在Products的Description(描述)裡面有"可樂"和"暢快"這兩個關鍵字
的內容撈出來,也就是用and的方法。
但是,我們常常需要用到or方法,例如要查詢"可樂"、"雪碧"。
那在用這種查詢方法,就沒辦法查的到了....
( 不可能會出現一種可樂是雪碧口味的吧= =)
ok~所以作者提出了另外一種方法,也就是使用了PredicateBuilder
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); }用Or方法,就可以用or來查詢"可樂"和"雪碧"。
讚吧!!果然是神人級的。
但是看到這邊,不要馬上貼上去使用阿~@@~
因為最重要最重要的關鍵是
我們還沒有PredicateBuilder這個類別阿。
這裡有兩個方法可以使用這個類別。
一、去作者網站下載LinqKit
二、去作者網站將PredicateBuilder的程式碼複製貼上
( 兩個都夠簡單吧= = )
最後,要補充一下,
如果是使用Linq to Entity的話,要把程式碼的最後一行改為
return objectContext.Products.AsExpandable().Where (predicate);也就是如下程式碼。
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 objectContext.Products.AsExpandable().Where (predicate); }另外,如果要查名子、描述、發行公司等等
很多TextBox的話,怎麼辦呢?
就改成這樣。
var predicate = PredicateBuilder.False(); predicate = predicate.Or(p => p.name.Contains(要查詢的)); predicate = predicate.Or(p => p.Description.Contains (要查詢的)); objectContext.Products.AsExpandable().Where (predicate);這樣擴充有沒有很容易呢!?
最後,這些我都還沒實驗過,實驗完後,我會再修改這篇文章,
將正確的訊息貼上。