使用Expression进行查询拼接

Lambda表达式 c# 经验谈:巧用Expression表达式 解决类似于sql中 select in 的查询(适合于中小型项目)

使用Expression进行查询拼接

linq实现And或Or的拼接的动态查询方式

EntityFramework4.5使用Expression类创建动态查询及动态查询导航属性

 

http://www.albahari.com/nutshell/linqkit.aspx

Dynamically Composing Expression Predicates

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

 http://msdn.microsoft.com/zh-cn/library/bb397951.aspx

 LINQ与DLR的Expression tree(1):简介LINQ与Expression tree

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

http://www.cnblogs.com/nanxiaoxiang/archive/2013/01/07/2849818.html

 

 

public IQueryable<BBS_Theme> GetListPage( int PageSize, int PageIndex, NameValueCollection nvcParamWhere, NameValueCollection nvcorderby, ref int AllCount)
       {
           #region where
           var searchPredicate = PredicateExtensions.True<BBS_Theme>();
           if (nvcParamWhere != null )
           {
               foreach ( string key in nvcParamWhere)
               {
                   string condition = string .Empty;
                   switch (key)
                   {
                       #region
                       case "ID" :
                           condition = nvcParamWhere[key];
                           searchPredicate = searchPredicate.And(u => u.ID.Equals(condition));
                           break ;
                       case "LableID" :
                           condition = nvcParamWhere[key];
                           searchPredicate = searchPredicate.And(u => u.LableID.Equals(condition));
                           break ;
 
           
                       
                       default :
                           break ;
 
                       #endregion
                   }
               }
           }
           #endregion
           
           #region queryable
           var linq = (from a in db.BBS_Theme
                       select a)
                       .Where(searchPredicate);
           #endregion
           
           #region orderby
           if (nvcorderby != null )
           {
               foreach ( string key in nvcorderby)
               {
                   string condition = string .Empty;
 
                   switch (key)
                   {
                       case "ID" :
                           condition = nvcorderby[key];
                           if ( bool .Parse(condition))
                           {
                               linq = linq.OrderBy(o=>o.ID);
                           }
                           else
                           {
                               linq = linq.OrderByDescending(o => o.ID);
                           }
                           break ;
                       //........省略n个case
                       
                       default :
                           break ;
 
                   }
               }
           }
           #endregion
           
           AllCount = linq.Count();
           linq = linq.Skip(PageSize * (PageIndex - 1)).Take(PageSize);
           return linq;
       }
 

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)&& amp;XX1=True&&XX1=XX1,肖博前辈说的无效(相对于我们需要的表达式无效,其实还是有效) (True||XX)||XX1=True||XX1=True(这里你不会看见where条件)。

2:构造函数使用False时:

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

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

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值