LINQ大家都知道,用起來也還不錯,但有一個問題,當你用Linq進行搜索的時候,你是這樣寫的
OK,看起來很好,不過····如果你要進行動態搜索的話··呵呵!其實方法還是挺多,只不過繞大彎
動態搜索是什麼?順便介紹下,假如你做了一個表格頁面,有用戶名、注冊時間、等級三列,你希望實現動態組合搜索,只有當用戶指定了要以用戶名搜索的時候才把用戶名這一列加入搜索條件,傳統的sql是這麼干的
聲明:只做示例,能不能運行不重要!(上面的代碼一般情況下必須是有問題的)
那你用linq能不能這麼干呢?呃····向下面這樣
對,是可以這樣,但在實際項目中一般是不會直接返回IQueryable接口的,也就沒辦法這麼做。
所以,動態拼接linq就應運而生了,而linq的實質是表達式樹,大家可以看IQueryable的Where擴展方法的簽名,是以Expression開頭的。
封裝的最初目的,也是給自己用。我是懶人,所以我會把組件搞得越簡單越好,下面是一個完整的使用示例
上面的代碼拼接出來表達式樹是這樣的
注釋已經說得比較清楚了,但第2行和第10行需要特別解釋一下,第10行的Build方法原型如下
返回值是一個Expression<Func<TParameter,bool>>類型的,其中有一個泛型參數,這個參數就是第2行實例化的時候傳的User,在使用的時候,必須保證添加的每一個搜索條件的屬性在User類裡面有。
為什麼要這樣設計呢?這個感覺一下子說不清楚,等下講原理的時候說
另外還可以看到有個filterNameMap的參數,這個主要是用來進行屬性名的轉換的,一般用於外鍵。簡單說一下我當時的設計意圖。
例如,有一個列表,展示的是權限系統中的角色信息,有角色名、描述、擁有的功能三列,其中第三列內容是來自功能表中的,其他是來自角色表的。
一般情況下可能會將第三列的屬性名設置為Privileges,然後類型是string型,但如果說用戶要按角色擁有的功能進行搜索,你不可能按字符串過濾吧?一般是按照功能Id也就是PrivilegeId過濾。
因為我用的是ExtJs(沒用過這個的直接跳過這一段吧),所以問題來了,extjs傳給我的參數名是Privileges,值是一個集合,因為我的Model類屬性名是這個,但我後台用於過濾的真正屬性是PrivilegeId,所以我需要將Privileges映射到PrivilegeId,告訴ExpressionBuilder,如果遇到了Privileges屬性名的搜索條件,就將屬性名換成PrivilegeId進行拼接
為了方便理解,下面是SqlFilter的源碼,很簡單
下面是Operation的
還真沒把握能說清楚···
其實就是拼接表達式樹的原理
這是一個相當簡單的表達式樹,注釋寫得很清楚,下面來個復雜的
可以看到,第一句都是取了User的類型,所以我在設計ExpressionBuilder的使用了泛型,以供傳入這個參數
原理就到這兒吧,要看更多的示例就直接看源碼吧
繼續廣告···要了解相關技術的請進QQ群74522853,答案XLinq