继LINQ动态组合查询PredicateExtensions讲解

        在LINQ动态组合查询中我留下了一个问题就是PredicateExtensions。在这里很简单不需要什么多的基础只要比会And、Or逻辑运算数学知识就够了。

先贴上代码好分析:

 


代码

public static class PredicateExtensions
    {
        public static Expression<Func<T, bool>> True<T>() { return f => true; }

        public static Expression<Func<T, bool>> False<T>() { return f => false; }

        public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expression1, 
           Expression<Func<T, bool>> expression2)
        {
            var invokedExpression = Expression.Invoke(expression2, expression1.Parameters
                    .Cast<Expression>());

            return Expression.Lambda<Func<T, bool>>(Expression.Or(expression1.Body, invokedExpression),
            expression1.Parameters);
        }

        public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1, 
              Expression<Func<T, bool>> expression2)
        {
            var invokedExpression = Expression.Invoke(expression2, expression1.Parameters
                 .Cast<Expression>());

            return Expression.Lambda<Func<T, bool>>(Expression.And(expression1.Body, 
                   invokedExpression), expression1.Parameters);
        }
    }

 

 

      在其中只有四个方法,True、False、Or、And,一看大家就知道这里是对逻辑运算操作。其中True、False是对表达式进行初始化,在我没有看见这个类之前我用的是null,用null这要在没有And,Or逻辑操作时进行Null判断,如果null则返回后一个表达式。而在这里有了true,fakse这相当于初始化了一个表达式,就不用再那么麻烦了。

     True、False的初始化有一个规则就是不能影响我们的正常表达式.在我们刚学语言的时候就有:逻辑与一假为假,逻辑或一真为真,那这句就可以运用于我们的这两表达式的初始化了。当我们在True、False初始化表达式和后便连接的表达式逻辑运算为And时候,我们就该用True,这么这个逻辑条件的真假取决于我们的后面表达式(逻辑与一假为假,一真那么还不确定),是不是没有影响我们的正常表达式?同理逻辑运算为Or时候,就该用False(逻辑或一真为真,一假也不确定,就取决于另一个表达式)。是不是很简单,还是那句话,我这种鼠辈估计很难想到,是应试教育禁锢了我们的思维啊!

      And、Or这是表达式逻辑运算连接,那主体为取出左边表达式body Invoke了再与右边表达式连接返回。

     为了验证我的结论,我们做几个小测试(这里为了方便改为了控制台程序):

测试1:True and连接;

 


代码

public static void Test1()
        {
            DbDataContext db = new DbDataContext();
            Expression<Func<TemplateDocument, bool>> expressleft = 
                                PredicateExtensions.True<TemplateDocument>();
            expressleft = expressleft.And(t => t.CategoriesID > 3);

            Expression<Func<TemplateDocument, bool>> expressright = 
                                PredicateExtensions.True<TemplateDocument>();
            expressright = expressright.And(t => t.CategoriesID < 5);

          expressleft=  expressleft.Or(expressright);
          var sql = db.GetCommand(db.TemplateDocument.Where(expressleft).Select(t => new { 
                           t.TemplateID, t.TemplateName, t.CategoriesID })).CommandText;
            Console.WriteLine(sql);

        }

 

 

输出sql:

 

SELECT [t0].[TemplateID], [t0].[TemplateName], [t0].[CategoriesID] 

FROM [dbo].[TemplateDocument] AS [t0] 

WHERE ([t0].[CategoriesID] > @p0) OR ([t0].[CategoriesID] < @p1)

 

 

不知你发现没有Linq表达式已经把True条件智能的去掉了,(True&&XX1)||(True&&XX2) = XX1||XX2。按照上面的说法,那我们把第一个条件改为False 的Or连接也应该一样,测试一下:

测试2


代码

public static void Test2()
        {
            DbDataContext db = new DbDataContext();
            Expression<Func<TemplateDocument, bool>> expressleft = 
                             PredicateExtensions.False<TemplateDocument>();//上例True该为False
            expressleft = expressleft.Or(t => t.CategoriesID > 3);//上例And该为Or

            Expression<Func<TemplateDocument, bool>> expressright = 
                              PredicateExtensions.False<TemplateDocument>();
                          //上例True该为False
            expressright = expressright.Or(t => t.CategoriesID < 5);
                          //上例And该为Or
            expressleft = expressleft.Or(expressright);
            var sql = db.GetCommand(db.TemplateDocument.Where(expressleft).Select(t => new { 
                         t.TemplateID, t.TemplateName, t.CategoriesID })).CommandText;
            Console.WriteLine(sql);

        }

 

输出sql

SELECT [t0].[TemplateID], [t0].[TemplateName], [t0].[CategoriesID] 

FROM [dbo].[TemplateDocument] AS [t0]

WHERE ([t0].[CategoriesID] > @p0) OR ([t0].[CategoriesID] < @p1)

 

和上例输出了sql完全一样,,(False||XX1)||(False||XX2) = XX1||XX2。那我们改变用法将True或Or连接呢?

测试3:


代码

public static void Test3()
        {
            DbDataContext db = new DbDataContext();
            Expression<Func<TemplateDocument, bool>> expressleft =
                                 PredicateExtensions.True<TemplateDocument>();
            expressleft = expressleft.Or(t => t.CategoriesID > 3);

            Expression<Func<TemplateDocument, bool>> expressright = 
                PredicateExtensions.False<TemplateDocument>();
                                    expressright = expressright.Or(t => t.CategoriesID < 5);

            expressleft = expressleft.And(expressright);
            var sql = db.GetCommand(db.TemplateDocument.Where(expressleft).Select(t => new { 
                                    t.TemplateID, t.TemplateName, t.CategoriesID })).CommandText;
            Console.WriteLine(sql);

        }

 


输出sql:

SELECT [t0].[TemplateID], [t0].[TemplateName], [t0].[CategoriesID] 
FROM [dbo].[TemplateDocument] AS [t0] 
WHERE [t0].[CategoriesID] < @p0 

 


恩 只有一个表达式了,当然了啊,你第一个表达式是(True||XX1)&&(False||XX2) = True&&XX2=XX2.做了这个测试,我真的很佩服微软,在代码中能够这么智能判断。索性把条件完全弄掉,我们把中间的And改为Or:(True||XX1)||(False||XX2) = True||XX2=True。这个就自己


测试了你将看不到where条件了。 肖坤Linq动态查询与模糊查询(带源码示例)中给出了一个结果总结.

  1:构造函数使用True时:单个AND有效,多个AND有效;单个OR无效,多个OR无效;混合时写在AND后的OR有效 
  2:构造函数使用False时:单个AND无效,多个AND无效;单个OR有效,多个OR有效;混合时写在OR后面的AND有效

我们来验证验证:

1构造函数使用True时:

(1):单个AND有效,多个AND有效,当然了True&&XX=XX

(2):单个OR无效,多个OR无效:True || XX=True所以无效。

(3):混合时写在AND后的OR有效:(True&&XX)||XX1=XX||XX1有效,(True||XX)&&XX1=True&&XX1=XX1,肖博前辈说的无效(相对于我们需要的表达式无效,其实还是有效) (True||XX)||XX1=True||XX1=True(这里你不会看见where条件)。

2:构造函数使用False时:

   和True情况一样,我就不去推导了,偷个懒。 

以上全是个人意见,如果有什么不对了请指导,更正。

作者:破  狼 
出处:http://www.cnblogs.com/whitewolf/ 
本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。该文章也同时发布在我的独立博客中-个人独立博客博客园--破狼51CTO--破狼。http://www.cnblogs.com/whitewolf/archive/2010/08/02/1790390.html

时间: 2024-10-29 10:54:32

继LINQ动态组合查询PredicateExtensions讲解的相关文章

利用Java Reflection(反射)原理,在hibernate里面实现对单表、视图的动态组合查询

动态|视图|组合查询     Reflection 是 Java 程序开发语言的特征之一,它允许运行中的程序对自身进行访问,并能直接操作程序的内部属性.     Hibernate是一个面向Java环境的对象/关系数据库映射工具,基本上,每个表或者视图在hibernate里面都可以对应一个类,在此处,我们通过充分的利用这个类,来实现动态组合查询. 首先我们一起来看看这个函数的源代码:     /**     * 组合查询     * @param object 包含查询条件的对象     * @

LINQ to SQL运行时动态构建查询条件

在进行数据查询时,经常碰到需要动态构建查询条件.使用LINQ实现这个需求可能会比以前拼接SQL语 句更麻烦一些.本文介绍了3种运行时动态构建查询条件的方法.本文中的例子最终实现的都是同一个功 能,从Northwind数据库Customers表中搜索出CompanyName列带有keywords中任意元素的项.keywords是 个字符串数组,该数组长度在编译时是不确定的.思路及方法说明写在代码注释中. 1.表达式树 1 public static IEnumerable<Customers>

在Linq To EF中,如何用委托动态生成查询条件?

问题描述 代码如下,问题是如何动态返回:Expression<Func<Web_Base_News_Info,bool>>expression?有其它更好的办法也可以,谢谢.publicvoidTest(ContextExtctx,Params.FieldExtRepeaterfieldExt){//1.封装容器varft=newFieldTest<Web_Base_News_Info>();//封装key对应的变量ft._dictKey.Add(EnumsKV.Fie

用ADO的COMMAND对象实现对WEB数据库动态数据查询的方法

用ADO的COMMAND对象实现对WEB数据库动态数据查询的方法★ 林碧英众所周知,由于ASP技术的出现,使得Intranet的应用更加广泛深入.相当多的企业都建立了企业内部综合查询系统,如何快速.准确地查询企业内部信息是编写基于WEB技术应用程序必须要解决的主要问题.ASP提供了用ADO内置的3个主要对象Recordset.Connection和Command对WEB数据库进行操作.其中Connection的主要功能是建立与WEB数据库的链接:Command的主要功能是向WEB数据库传送数据查

蛙蛙推荐:asp中的多条件组合查询实现

条件|组合查询 <!-- 蛙蛙推荐:asp中的多条件组合查询实现多条件组合查询在很多地方都很有用,本文用一个简单的例子来实现一种组合查询在示例之前请确保你安装有sqlserver2000及其默认数据库NorhtWind.代码非常直观,加上关键部分我做了注释,所以很容易理解.需要注意的几个问题就是:1.在字符串连接的时候注意两个需要连接的串中第二个串的开头第一个字符应该打一个空格,这样不至于两个串的首尾相连成一个单词.2.righ的left函数取出的结构区分大小写,如果你字符串里用的是'and',

使用javascript实现一个高级组合查询控件(内含初步实现原型)

在很多项目中,特别是信息系统,查询功能占了项目的大部分:同时查询条件的组合要求丰富,因此实现起来变得复杂.一般情况下,我们只会实现有限的条件查询,如一个表的某几个重要的字段或者甚至所有的字段:当然,常规的情况下客户是足够用的,但一些高级的应用,如((字段1>10) or (字段2=5)) and 字段3 is not null) 这种复杂的条件组合,就不一定适合了,通常如果是固定几种组合模式,这样我们还可以在后台用语言(java.c#等)实现,要是条件组合是动态的,那么实现起来就相当麻烦了. 因

PgSQL · 应用案例 · GIN索引在任意组合查询中的应用

背景 很多人小时候都有一个武侠梦,独孤求败更是金庸武侠小说里的一位传奇人物. 纵横江湖三十馀载,杀尽仇寇奸人,败尽英雄豪杰,天下更无抗手,无可奈何,惟隐居深谷,以雕为友. 呜呼,生平求一敌手而不可得,诚寂寥难堪也. 独孤老前辈的佩剑描写非常有意思,从使用的佩剑,可以看出一个人的武功修为. 第一柄是一柄青光闪闪的无名利剑.「凌厉刚猛,无坚不摧,弱冠前以之与河朔群雄争锋.」 第二柄是紫薇软剑,「三十岁前所用,误伤义士不祥,乃弃之深谷.」 第三柄是玄铁重剑,「重剑无锋,大巧不工,四十岁之前恃之横行天下

Spring+Mybatis实现动态SQL查询

在报表类应用中,通常需要根据不同的维度去组合复杂的查询条件,然后构造SQL去执行查询.如果只是通过在程序中简单地拼接SQL语句,工作量会非常大,而且代码可能也非常难以维护.Mybatis支持动态SQL查询功能,可以通过配置动态的SQL来简化程序代码中复杂性,不过,这个颇有点XML编程的韵味,通过XML来处理复杂的数据判断.循环的功能,其实也很好理解. 准备工作 下面,我们首先创建一个MySQL示例表,如下所示: 01 CREATE TABLE `traffic_info` ( 02 `id` i

问个问题,根据3个条件进行组合查询

问题描述 我现在有个gridview点击button按钮直接查询全部数据然后现在想加一个根据三个条件进行组合查询应该怎么搞最好说的比较全面点 解决方案 解决方案二:通过你的表达,这应该很基础的东西.界面上增加三个输入控件(比如文本框或者列表控件等),点击查询的时候,通过输入控件的值去检索数据库,绑定girdview.解决方案三:正如楼上所说,通过增加界面上的控件,获得用户输入的更多的条件.在程序中则通过varw="where1=1";if(控件1.Text.Trim()!=string