Contents

使用LINQKit 動態OR條件查詢

使用LinqKit 動態OR條件查詢

LinqKit 是一套使用Linq時強大的輔助擴充,特別是處理OR條件,因為最近常用到,順便把之前的筆記整理一下,LinqKit 其實網路上也不少人介紹過了,特別推薦的文章放在參考,這邊只記錄程式碼用法。

環境

  • LinqPad 6
  • LinqKit
Note
求簡單,直接使用北風資料庫做示範

原始的Product列表

/static/使用LinqKit_動態OR條件查詢_71fef572d5364cc0b97d964b96c60d0d/2020-10-14_17-12-28.png

選擇CategoryID為2,4,6,8才顯示

一、使用LinqKit

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void Main()
{
	var selectedCategory = new List<int> { 2, 4, 6, 8 };
	FilterProducts(selectedCategory).AsEnumerable().Dump();
}

public IQueryable<Products> GetProducts()
{
	return Products.AsNoTracking();
}

public IEnumerable<Products> FilterProducts(List<int> selectedCategory)
{
	var product = GetProducts();
	
	var predicate = PredicateBuilder.New<Products>();
	
	if (selectedCategory.Count() > 0)
	{
		foreach (var categoryId in selectedCategory)
		{
			predicate = predicate.Or(x => x.CategoryID == categoryId);
		}
	}

	return product.Where(predicate);
}

二、使用Linq Contains 或 Any等

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
void Main()
{
	var selectedCategory = new List<int> { 2, 4, 6, 8 };
	FilterProducts(selectedCategory).AsEnumerable().Dump();
}

public IQueryable<Products> GetProducts()
{
	return Products.AsNoTracking();
}

public IEnumerable<Products> FilterProducts(List<int> selectedCategory)
{
	var product = GetProducts();

	if (selectedCategory.Count() > 0)
	{
		product = product.Where(x => selectedCategory.Contains(x.CategoryID.Value));
	}
	
	return product;
}
/static/使用LinqKit_動態OR條件查詢_71fef572d5364cc0b97d964b96c60d0d/2020-10-23_11-54-50.png /static/使用LinqKit_動態OR條件查詢_71fef572d5364cc0b97d964b96c60d0d/2020-10-23_15-40-15.png /static/使用LinqKit_動態OR條件查詢_71fef572d5364cc0b97d964b96c60d0d/2020-10-23_15-40-51.png

可以發現,兩者在SQL語法上,一個是使用OR,一個是使用IN,除此之外結果都是一樣的,看起來使用LinqKit似乎沒有太多的好處,還增加了不少複雜度,但如果現在加上,篩選SupplierID呢,這時候問題就會出現分歧,篩選SupplierID是屬於AND,還是OR呢?

增加Supplier條件

AND情況下

加上一個Where即可解決

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
public IEnumerable<Products> FilterProducts(List<int> selectedCategory,int? selectedSupplier = null)
{
	var product = GetProducts();
	
	if (selectedCategory.Count() > 0)
	{
		product = product.Where(x => selectedCategory.Contains(x.CategoryID.Value));
	}
	
	if (selectedSupplier != null)
	{
		product = product.Where(x => x.SupplierID == selectedSupplier);
	}
	
	return product;
}
/static/使用LinqKit_動態OR條件查詢_71fef572d5364cc0b97d964b96c60d0d/2020-10-23_15-20-17.png

OR情況下

這時候就會發現似乎並不那麼簡單,而LinqKit的價值也體現出來了

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
void Main()
{
	var selectedCategory = new List<int> { 2, 4, 6, 8 };
	// 為了方便呈現OR改成8
	int selectedSupplier = 8;
	FilterProducts(selectedCategory,selectedSupplier).AsEnumerable().Dump();
}

public IQueryable<Products> GetProducts()
{
	return Products.AsNoTracking();
}

public IEnumerable<Products> FilterProducts(List<int> selectedCategory,int? selectedSupplier = null)
{
	var product = GetProducts();
	
	var predicate = PredicateBuilder.New<Products>();

	if (selectedCategory.Count() > 0)
	{
		foreach (var categoryId in selectedCategory)
		{
			predicate = predicate.Or(x => x.CategoryID == categoryId);
		}
	}
	
	var predicateSupplier = PredicateBuilder.New<Products>();
	if (selectedSupplier != null)
	{
		predicateSupplier = predicateSupplier.Or(x => x.SupplierID == selectedSupplier);
	}
	// 兩者串接起來
	predicateSupplier = predicateSupplier.Or(predicate);
	return product.Where(predicateSupplier);
}
/static/使用LinqKit_動態OR條件查詢_71fef572d5364cc0b97d964b96c60d0d/2020-10-23_15-35-22.png

參考

搞搞就懂 使用 LINQKit PredicateBuilder 解決動態OR條件查詢窘境

https://dotblogs.com.tw/wasichris/2014/12/20/147734

LINQKit Github

https://github.com/scottksmith95/LINQKit