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操 ...
随机推荐
- [转] linux(debian)安装USB无线网卡(tp-link TL-WN725N rtl8188eu )
1: 台式机家里面不想再走线了. 于是去某东买了个USB无线网卡.tp的WN725N USB,非常小, 和罗技的优联接收器差不多大. 2: 驱动能自己识别是不指望了,既然是usb网卡,插入USB后 ...
- thinkphp AOP(面向切面编程)钩子和行为
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的 ...
- [转载]关于generate用法的总结【Verilog】
转载自http://www.cnblogs.com/nanoty/archive/2012/11/13/2768933.html Abtract generate语句允许细化时间(Elaboratio ...
- 最新Windows下c++读写锁SRWLock介绍
https://blog.csdn.net/MoreWindows/article/details/7650574 https://blog.csdn.net/chenzhjlf/article/de ...
- HTML5学习笔记(二十五):事件
在浏览器或文档某个元素发生某个特定情况的瞬间,会作为一个事件进行广播,我们可以对其添加监听来处理特定的事件. 事件流 事件流描述了页面中接收事件的顺序. 整个事件流包含了三个阶段:事件捕获阶段.事件目 ...
- 关于chrome的开发调试方式
chrome://inspect/#devices 调试移动设备app chrome://version 查看chrome浏览器版本信息 chrome://components/ 查看组件信息 上面的 ...
- android - 调用系统分享功能分享图片
step1: 编写分享代码, 将Uri的生成方式改为由FileProvider提供的临时授权路径,并且在intent中添加flag 注意:在Android7.0之后,调用系统分享,传入URI的时候可能 ...
- Android-一只手指滑动View,另一只手指按Home键,重新进入后View状态无法更新的问题
上午测试报了一个bug:说是一只手指拖动虚拟摇杆上的View滑块不松,另一只手指点击Home键将App压后台,重新进入的时候,View滑块卡死了. 刚开始看到这个问题感觉很奇怪,因为正常情况下,手指离 ...
- 每日英语:U.S. Media Firms Stymied in China
China's recent clampdown on foreign media is crimping the expansion plans of Western news organizati ...
- tensorflow笔记3:CRF函数:tf.contrib.crf.crf_log_likelihood()
在分析训练代码的时候,遇到了,tf.contrib.crf.crf_log_likelihood,这个函数,于是想简单理解下: 函数的目的:使用crf 来计算损失,里面用到的优化方法是:最大似然估计 ...