惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
H
Help Net Security
腾讯CDC
宝玉的分享
宝玉的分享
H
Hackread – Cybersecurity News, Data Breaches, AI and More
L
LangChain Blog
爱范儿
爱范儿
T
The Blog of Author Tim Ferriss
J
Java Code Geeks
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
MyScale Blog
MyScale Blog
Engineering at Meta
Engineering at Meta
N
Netflix TechBlog - Medium
D
Docker
V
V2EX
Last Week in AI
Last Week in AI
G
Google Developers Blog
IT之家
IT之家
C
Check Point Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
人人都是产品经理
人人都是产品经理
博客园 - 叶小钗
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 聂微东

博客园 - 海南K.K

海南海口滨海大道洛杉矶城一线海景公寓出售(09年建成,面积88~126平米共六套,一次性团购可打折) 出售海南海口南渡江畔私家别墅(楼高4层,占地388平米,建筑面积570平米) 代友发布:海南海口海景豪宅转让(16层5室3厅3卫2阳台288.0m²) 百度谈人生?别再往自己脸上贴金了! douban api,你到底想做什么? Javascript: 从最受误解的语言,到最流行的语言 LINQ那些事(9)-解析Table<T>.Attach引发的异常和解决方法 你可能不熟悉的CSS 三言二拍:海南的软件业 海口房事:海口纵贯线(-海南购房-海口购房-海南二手房-海口二手房-海南国际旅游岛-养老-过冬-) 海口房事:看京城人争当海南岛民 (-海南购房-海口购房-海南二手房-海口二手房-过冬-养老-国际旅游岛-) 海南海口生态公园公寓出售-海南购房-海口购房-海南二手房-海口二手房-过冬-养老-国际旅游岛- Code4Fun: 通过XML模板系统实现对象的灵活序列化 LINQ那些事儿(4)- Query Expression和Query Operator LINQ那些事儿(3)- 事务和并发冲突处理 LINQ那些事儿(2)- 简单对象的CRUD操作和Association的级联操作 LINQ那些事儿(1)- 定义从关系数据库到entity class的映射 LINQ那些事 LINQ那些事儿(6)-对象生命周期管理
LINQ那些事儿(5)- 动态查询
海南K.K · 2010-01-01 · via 博客园 - 海南K.K

本文讨论了在LINQ2SQL中执行动态查询的方法

所谓动态查询,是指查询条件或查询值都是在运行时才能确定的查询。这就意味着我们不能hard-code定义查询变量(query variable),只有根据查询时传递的条件来拼凑。下面我们看看几组不同条件组合的查询。

1) 用户输入查询条件:City为”London”且ContactName包含”Thomas”

public IQueryable<Customer> GetCustomers(string city, string contactName)
{
	var context = GenerateContext();
	IQueryable<Customer> result = context.Customers;

	if (!string.IsNullOrEmpty(city))
	{
		result = result.Where(c => c.City == city);
	}

	if (!string.IsNullOrEmpty(contactName))
	{
		result = result.Where(c => c.ContactName.Contains(contactName));
	}

	return result;
}

2) 用户输入查询条件:City为”London”或”Paris”

由于Where和Where的连接是表示AND的关系,所以我们无法用1)的方法来表达这个查询。有一个可以利用的query operator是Union:

var context = GenerateContext();
IQueryable<Customer> result = null;
string[] cities = { "London", "Paris" };

foreach (string item in cities)
{
    string tmp = item;
    result = result == null ?
    context.Customers.Where(c => c.City == tmp) :
    result.Union(context.Customers.Where(c => c.City == tmp));
}

context.Log = Console.Out;
Console.WriteLine(result.Count());

虽然结果符合我们的要求,但是通过输出的SQL语句,你可以看到对于这种方式构造的Expression Tree,SQL并没有我们想要的精简(我们期望的是t0.City=’London’ OR t0.City=’Paris’)。输出SQL如下:

SELECT COUNT(*) AS [value]
FROM (
    SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[Cont
actTitle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[
Country], [t0].[Phone], [t0].[Fax]
    FROM [dbo].[Customers] AS [t0]
    WHERE [t0].[City] = @p0
    UNION
    SELECT [t1].[CustomerID], [t1].[CompanyName], [t1].[ContactName], [t1].[Cont
actTitle], [t1].[Address], [t1].[City], [t1].[Region], [t1].[PostalCode], [t1].[
Country], [t1].[Phone], [t1].[Fax]
    FROM [dbo].[Customers] AS [t1]
    WHERE [t1].[City] = @p1
    ) AS [t2]

另外的方法就是是根据所有查询条件和查询值,给Where构造一个Expession。首先来看看Where的签名:

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:

var context = GenerateContext();
Expression<Func<Customer, bool>> filter = PredicateBuilder.False<Customer>();
string[] cities = { "London", "Paris" };

foreach (string item in cities)
{
    string tmp = item;
    filter = filter.Or(c => c.City == tmp);
}

context.Log = Console.Out;
context.Customers.Where(filter).Count().Dump();

输出的SQL也是我们期待的结果

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

最后,如果你对以前拼接SQL语句的方式还是念念不忘的话,可以去用Dynamic LINQ,参考SocttGu’s Blog

参考资料:

PredicateBuilder http://www.albahari.com/nutshell/predicatebuilder.aspx

Dynamic LINQ  http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

链接

1、 LINQ那些事儿(1)- 定义从关系数据库到Entity Class的映射

2、 LINQ那些事儿(2)- 简单对象的CRUD操作和Association的级联操作

3、 LINQ那些事儿(3)- 事务和并发冲突处理

4、 LINQ那些事儿(4)- Query Expression和Query Operator

5、 LINQ那些事儿(5)- 动态查询

6、 LINQ那些事儿(6)- DataContext的对象生命周期管理

7、 LINQ那些事儿(7)- 通过自定义IEnumerable<T>来扩展LINQ

8、LINQ那些事儿(8)- 通过自定义IQueryable<T>和IQueryableProvider来扩展LINQ