zoukankan      html  css  js  c++  java
  • 使用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] > @p0OR ([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] > @p0OR ([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情况一样,我就不去推导了,偷个懒。

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

     

  • 相关阅读:
    【转】acm小技巧
    poj-1703-Find them, Catch them
    poj-1611-The Suspects
    poj-2236-Wireless Network
    hdu-4496-D-City
    hdu-1213-How Many Tables
    hdu-1856-More is better
    gcd和ex_gcd
    递归趣文
    算法实质【Matrix67】
  • 原文地址:https://www.cnblogs.com/shiningrise/p/2986836.html
Copyright © 2011-2022 走看看