linq to sql之组装where条件下的'或'语句
之前遇到过类似的需求,即前台传入几个过滤条件,后台动态组装where。
例如,前台传入name='张三',age=10, 其余的字段,类似email,QQ之类的本次查询时不做过滤。
用linq to sql来组装where语句非常方便。
var f= db.Users.Where(x => true);
if(!string.IsNullOrWhiteSpace(name))
f= f.Where(x=>x.Name == name);
if(age != null)
f= f.Where(x=>x.Age == age);
var data = f.ToList();
今天碰到另一种情况。状态的多种可能性。用户的注册邮箱有多个状态(用int表示):未验证null,无效-1,有效0,退订-2,查看(>0的值)等。前台过滤时,可能勾选多个状态,例如未验证 或 有效 或 查看。用后台的where表示,就是:
Where(x => x.EmailState == null || x.EmailState == || x.EmailState > )
问题出现了。这里有五种状态,每个状态有前台选中和未选中两种情况,组合的情况最多有2^5 = 32种。用32个if来解决这里的问题,不是不可以,只是代码会显得很笨重,而且扩展性很差,如果以后出现第六个、第七个状态......T_T...T_T
首先想到的,能不能像上面的where组装那样实现。答案是不行。上面的where很明显是逻辑and运算。而这里应该是单个where情况下的or运算。
解决思路:用Func<Users,bool>来表示每一个邮箱状态对应的过滤语句。对勾选的每一个状态,对它们的过滤语句执行'||'运算。
filter1(x) || filter2(x) || filter3(x)...
代码方案一:
Func<Users, bool> filter = x => false;
if (chkEmailUnverify.Checked) filter = x => filter(x) || x.SendMail == null;
if (chkEmailUnsubscribe.Checked) filter = x => filter(x) || x.SendMail == -;
if (chkEmailInvalid.Checked) filter = x => filter(x) || x.SendMail == -;
if (chkEmailValid.Checked) filter = x => filter(x) || x.SendMail == ;
if (chkEmailOpen.Checked) filter = x => filter(x) || (x.SendMail.HasValue && x.SendMail.Value > );
对勾选的每一个状态,在之前的Func<Users,bool>基础上执行||运算。理论上来讲应该行得通,但是实际上调试的时候发现,只要超过两个勾选,就会报错:

提示堆栈溢出。呃...对这类问题一直比较怵,对clr不了解。只能做猜测:因为filter本身就是代理,而代理的执行有延迟的特性,所以这里filter = x => filter(x)...可能会出现无限向下发展的情况。寻求曲线解决。
代码方案二:
Func<Users, bool> filter = x => true;
List<Func<int?, bool>> list = new List<Func<int?, bool>>() { x => false };
if (chkEmailUnverify.Checked) list.Add(x => x == null);
if (chkEmailValid.Checked) list.Add(x => x == );
if (chkEmailOpen.Checked) list.Add(x => x > );
if (chkEmailUnsubscribe.Checked) list.Add(x => x == -);
if (chkEmailInvalid.Checked) list.Add(x => x == -); filter = x => list.Select(c => c(x.SendMail)).Aggregate((a, b) => a || b);
好吧,我承认只是在之前的那个思路基础上加了一个外壳。壳的主要思想是避免出现filter = x => filter(x) || x.Shield == 'value'。
可能上面的考虑有些道理,这次的方案通过了编译,也取得了我要的结果。大功告成~o(∩_∩)o
调用时的代码:
var f= db.Users.Where(filter);
如有错误,欢迎留言指导。
为MH370祈福~
linq to sql之组装where条件下的'或'语句的更多相关文章
- LINQ之路10:LINQ to SQL 和 Entity Framework(下)
在本篇中,我们将接着上一篇“LINQ to SQL 和 Entity Framework(上)”的内容,继续使用LINQ to SQL和Entity Framework来实践“解释查询”,学习这些技术 ...
- LINQ To SQL在N层应用程序中的CUD操作、批量删除、批量更新
原文:LINQ To SQL在N层应用程序中的CUD操作.批量删除.批量更新 0. 说明 Linq to Sql,以下简称L2S. 以下文中所指的两层和三层结构,分别如下图所示: 准确的说,这里 ...
- 深入理解 LINQ to SQL 生成的 SQL 语句
Ø 简介 在 C# 中与数据交互最常用的语句就是 LINQ 了,而 LINQ to SQL 是最直接与数据库打交道的语句,它可以根据 LINQ 语法生成对应的 SQL 语句,在数据库中去执行.本文主 ...
- LINQ之路 9:LINQ to SQL 和 Entity Framework(上)
在上一篇中,我们从理论和概念上详细的了解了LINQ的第二种架构“解释查询”.在这接下来的二个篇章中,我们将使用LINQ to SQL和Entity Framework来实践“解释查询”,学习这些技术的 ...
- Linq to Sql:N层应用中的查询(下) : 根据条件进行动态查询
原文:Linq to Sql:N层应用中的查询(下) : 根据条件进行动态查询 如果允许在UI层直接访问Linq to Sql的DataContext,可以省去很多问题,譬如在处理多表join的时候, ...
- LINQ系列:LINQ to SQL Where条件
1. 单一条件查询 var expr = context.Products .Where(p => p.ProductName == "LINQ to SQL"); SELE ...
- Linq to sql 实现多条件的动态查询(方法一)
/// <summary> /// Linq to sql 多字段动态查询 /// </summary> /// <returns></returns> ...
- LINQ to SQL语句(7)之Exists/In/Any/All/Contains
适用场景:用于判断集合中元素,进一步缩小范围. Any 说明:用于判断集合中是否有元素满足某一条件:不延迟.(若条件为空,则集合只要不为空就返回True,否则为False).有2种形式,分别为简单形式 ...
- 年终巨献 史上最全 ——LINQ to SQL语句
LINQ to SQL语句(1)之Where 适用场景:实现过滤,查询等功能. 说明:与SQL命令中的Where作用相似,都是起到范围限定也就是过滤作用的,而判断条件就是它后面所接的子句.Where操 ...
随机推荐
- [转]Greenplum的工作负载及资源管理
工作负载及资源管理 查询分析-查看EXPLAIN输出 EXPLAIN输出一个计划为节点组成的树 每个节点表示一个独立的操作 计划应该从下向上读,每个节点得到的记录向上传递 成本评估项: cost - ...
- Python 爬虫编码格式问题 gb2312转换utf8
遇到的问题是:爬取网页得到的结果如下(部分) 里面的中文出现乱码. <!DOCTYPE html> <html lang='zh-CN'> <head> < ...
- Zookeeper服务器配置项详解
文章转自: http://www.bug315.com/article/159.htm http://www.bug315.com/article/160.htm Zookeeper是通过一个***. ...
- 如何使你的Android应用记住曾经使用过的账户信息
原文:http://android.eoe.cn/topic/android_sdk 当您记住他们的名字时,每个人都会很喜欢.最简单的一个例子,您能够做的,让您的应用更加受人喜爱的,最有效的方法是记住 ...
- Android 源码阅读笔记
Zygote: .Zygote 是系统启动之后创建的第二个进程2.Zygote 创建zygote Socket.虚拟机3.Zygote 在虚拟机中通过forkSystemServer, 创建Serve ...
- Android API Guides---Drag and Drop
Drag and Drop 随着Android拖/放框架,能够同意用户将数据从一个视图使用图形拖动移动到还有一个查看当前布局和下降的手势. 该框架包含一个拖放事件类,拖累听众和辅助方法和类. 尽管该框 ...
- kvm 给虚机增加网卡
[root@666 ok]# virsh domiflist c03 Interface Type Source Model MAC --------------------------------- ...
- HTML5学习笔记(二):HTML基础学习之二
表单 表单用来传递用户数据,多用来与后端进行数据交互. 前端: <!DOCTYPE html> <html lang="en"> <head> ...
- HTML5学习笔记(二):HTML基础学习之一
元素.属性和格式化 元素是指开始标签到结束标签之前的所有代码,如: <p>this is my page!</p> <!-- 下面的可以称为空元素 --> < ...
- Fluent 18.0新功能之:其他
ANSYS 18.0在2017年1月底发布,来看看Fluent18.0更新了哪些内容. 1 用户界面 关于用户界面方面的更新包括: (1)可以在树形菜单中同时选择多个子节点,如同时选择多个边界,点击右 ...