在上一篇介紹完了會使用到的ViewModel之後,接下來就是實際的商業邏輯,也就是實際做搜索和產生資料的部份。
在這一篇,將會介紹如何透過Service層和ViewModel的搭配,讓使用起來變的更加方便。
Service的流程大概如下:
由於Service要做的事情也滿多的,因此整個Service層的實作會分幾篇來介紹。
這個部份其實要拆成兩塊:
基本上,動態組裝Linq條件有3種方法:
自己寫Expression Tree
基本上Linq的Where條件最終組出來就是一個Expression Tree。因此如果對於Expression Tree有所瞭解可以自己動手寫。
但是基本上要會寫這個要對於整個比較瞭解,因此基本不用考慮。
使用PredicateBuilder
PredicateBuilder基本上就是可以用強型別的方式組裝Linq條件。舉例來說,我們使用Linq來寫Where條件,當Where條件寫好只好,是沒有辦法在對那個Where條件在做調整。
因此,假設我們的搜索表單有4個條件,有輸入才做搜索條件,如果條件是兩個以上,還要做and的邏輯。要用原生的linq做到這個其實是很困難的,因為Linq條件是不能在改,因此等於每一種情況都要寫一個,這個很難維護也很麻煩。
因此,PredicateBuilder就很方便,它能夠讓我們動態修改Linq條件,因此舉例來說(官方的例子):
IQueryable<Product> SearchProducts (params string[] keywords)
{
var predicate = PredicateBuilder.False<Product>();
foreach (string keyword in keywords)
{
string temp = keyword;
predicate = predicate.Or (p => p.Description.Contains (temp));
}
return dataContext.Products.Where (predicate);
}
有一堆搜索的Keyword,每一個要以Or的方式做搜索,不是用PredicateBuilder,原生的Linq是辦不到的(如果全部要做and是做的到,但是or就沒有辦法)。
LinqKit 套件
PredicateBuilder屬於LinqKit套件的一部份,這個套件提供了一些方便處理Linq的方法。
PredicateBuilder非常適合在確定有那些欄位的情況下使用。例如確定有4個搜索欄位。但是,這個不適合我們使用。因為如果要寫共通處理邏輯,更本就不知道有那些搜索欄位。
Dynamic Linq Query
早期在寫Sql的時候,有時候Sql的語法使用string組裝在一起(當然要用NameParameter避免Sql injection)。這一種組裝的好處是完全可以寫好一個共用邏輯,只要符合條件的就用string concat的方式組裝條件,非常的方便。
Linq如果可以做到就好了,因此由Scot Gu介紹了一個所謂的Dynamic Linq Query - Dynamic LINQ
Dynamic Linq Query基本上就是可以讓我們用string方式組裝linq,因此(下面範例是由保哥一篇介紹的文章裡面截取):
Northwind db = new Northwind(connString);
db.Log = Console.Out;
var query =
db.Customers.Where("City == @0 and Orders.Count >= @1", "London", 10).
OrderBy("CompanyName").
Select("New(CompanyName as Name, Phone)");
Console.WriteLine(query);
Console.ReadLine();
Dynamic Linq Query
基本上這個功能並沒有包含在.Net裡面,如果要使用之前是需要到Scott Gu的那篇文章下載dll。不過有人把它包到了Nuget,方便使用
Dynamic Linq Query非常適合做那種通用型的處理,例如不知道欄位有什麼的情況下。但是壞處是,喪失了強型別的好處。不過這個非常適合框架處理搜索條件。
本來這一篇還要介紹框架Service層如何搭配Dynamic Linq Query來使用,不過在介紹動態Linq條件的時候,篇幅有點長,因此就把Service層的實作留在下一篇。