程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> LINQ那些事兒(5)- 動態查詢

LINQ那些事兒(5)- 動態查詢

編輯:關於.NET

所謂動態查詢,是指查詢條件或查詢值都是在運行時才能確定的查詢。這就意味著我們不能hard-code定義查詢變量(query variable),只有根據查詢時傳遞的條件來拼湊。下面我們看看幾組不同條件組合的查詢。

1) 用戶輸入查詢條件:City為”London”且ContactName包含”Thomas”

01 public IQueryable<Customer> GetCustomers(string city, string contactName)
02 {
03     var context = GenerateContext();
04     IQueryable<Customer> result = context.Customers;
05
06     if (!string.IsNullOrEmpty(city))
07     {
08         result = result.Where(c => c.City == city);
09     }
10
11     if (!string.IsNullOrEmpty(contactName))
12     {
13         result = result.Where(c => c.ContactName.Contains(contactName));
14     }
15
16     return result;
17 }

2) 用戶輸入查詢條件:City為”London”或”Paris”

由於Where和Where的連接是表示AND的關系,所以我們無法用1)的方法來表達這個查詢。有一個可以利用的query operator是Union:

01 var context = GenerateContext();
02 IQueryable<Customer> result = null;
03 string[] cities = { "London", "Paris" };
04
05 foreach (string item in cities)
06 {
07     string tmp = item;
08     result = result == null ?
09     context.Customers.Where(c => c.City == tmp) :
10     result.Union(context.Customers.Where(c => c.City == tmp));
11 }
12
13 context.Log = Console.Out;
14 Console.WriteLine(result.Count());

雖然結果符合我們的要求,但是通過輸出的SQL語句,你可以看到對於這種方式構造的Expression Tree,SQL並沒有我們想要的精簡(我們期望的是t0.City=’London’ OR t0.City=’Paris’)。輸出SQL如下:

01 SELECT COUNT(*) AS [value]
02 FROM (
03     SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[Cont
04 actTitle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[
05 Country], [t0].[Phone], [t0].[Fax]
06     FROM [dbo].[Customers] AS [t0]
07     WHERE [t0].[City] = @p0
08     UNION
09     SELECT [t1].[CustomerID], [t1].[CompanyName], [t1].[ContactName], [t1].[Cont
10 actTitle], [t1].[Address], [t1].[City], [t1].[Region], [t1].[PostalCode], [t1].[
11 Country], [t1].[Phone], [t1].[Fax]
12     FROM [dbo].[Customers] AS [t1]
13     WHERE [t1].[City] = @p1
14     ) AS [t2]

另外的方法就是是根據所有查詢條件和查詢值,給Where構造一個Expession。首先來看看Where的簽名:

1 IQueryable<T> Where<T>(this IQueryable<T> source, Expression<Func<T, bool>> predicate)

對於這樣一個Expression,如果你熟悉Expression Tree的構造方法,完全可以自己寫。《C# 3.0 In Nutshell》的作者寫了一個小巧的PrediateBuilder,可以幫助我們用lambda expression快速構造這樣的expression:

01 var context = GenerateContext();
02 Expression<Func<Customer, bool>> filter = PredicateBuilder.False<Customer>();
03 string[] cities = { "London", "Paris" };
04
05 foreach (string item in cities)
06 {
07     string tmp = item;
08     filter = filter.Or(c => c.City == tmp);
09 }
10
11 context.Log = Console.Out;
12 context.Customers.Where(filter).Count().Dump();

輸出的SQL也是我們期待的結果

1 SELECT COUNT(*) AS [value]
2 FROM [dbo].[Customers] AS [t0]
3 WHERE ([t0].[City] = @p0) OR ([t0].[City] = @p1)

最後,如果你對以前拼接SQL語句的方式還是念念不忘的話,可以去用Dynamic LINQ,參考SocttGu’s Blog。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved