none
linq 动态查询Expression RRS feed

  • 问题

  • public List<SYS_PROJECTS> SearchAllProjects(SYS_PROJECTS needSearchProj)
        {
          List<SYS_PROJECTS> projList = new List<SYS_PROJECTS>();
          if (needSearchProj == null)
          {
            var sys_ProjectTB = new C_ProjectEntities().SYS_PROJECTS.AsEnumerable();
            projList = (from c in sys_ProjectTB select c).ToList();
          }
          else
          {
            var projProperties = needSearchProj.GetType().GetMembers().Where(c => c.MemberType == System.Reflection.MemberTypes.Property).Where(c => c.Name!= "PROJECT_ID" && c.Name != "EntityState" && c.Name != "EntityKey").ToList();
            //动态查询声明查询参数"b"
            ParameterExpression b = Expression.Parameter(typeof(SYS_PROJECTS), "b");
            //声明被查询的表为SYS_PROJECTS
            IQueryable<SYS_PROJECTS> queryProj = new C_ProjectEntities().SYS_PROJECTS;
            foreach(var item in projProperties) 
            {
              //声明查询的属性
              Expression left = Expression.Property(b, typeof(SYS_PROJECTS).GetProperty(item.Name));
              //对该属性进行模糊查询 例如:%%
              Expression right = Expression.Call
                (
                  left,
                  typeof(string).GetMethod("IndexOf", new Type[] { typeof(string)}),
                  Expression.Constant(needSearchProj.GetType().GetProperty(item.Name).GetValue(needSearchProj, null))
                );
              //定义模糊查询的表达式为...indexof>=0
              Expression queryPram = Expression.GreaterThanOrEqual(right, Expression.Constant(0));
              Expression ifQuery = Expression.IfThenElse
                        (
                          queryPram,
                          Expression.LessThan(right, Expression.Constant(0)),
                          queryPram
                        );
             
                      Expression pred = Expression.Lambda
                      (
                        ifQuery, 
                        b
                      );
              //生成Lambda表达式:Where(b=>b.IndexOf("")>=0)
              Expression expr = Expression.Call
              (
                  typeof(Queryable), "Where",
                  new Type[] { typeof(SYS_PROJECTS) },
                  Expression.Constant(queryProj), pred
              );
              //生成动态查询
              IQueryable<SYS_PROJECTS> selectQueryProj = queryProj.Provider.CreateQuery<SYS_PROJECTS>(expr);
            }
    

    这是我针对一张表的动态模糊查询,当属性有值时执行indexof()>=0没有值时执行indexof()<0的Expression 

    生成的where  lambda表达式类似   where(c=>c.Name.IndexOf("张")>=0?c.Name.IndexOf("张")>=0:c.Name.IndexOf("张")<0);

    但是采用动态生成lambda时在

     Expression expr = Expression.Call
                        (
                                typeof(Queryable), "Where",
                                new Type[] { typeof(SYS_PROJECTS) },
                                Expression.Constant(queryProj), pred
                        );

    处报出异常:    类型“System.Linq.Queryable”上没有与提供的类型参数和参数兼容的泛型方法“Where”。如果方法是非泛型的,则不应提供类型参数。

    请问该怎样解决?

    2011年7月20日 12:25

全部回复

  • 还不能完全理解 不过之前看过一篇 和你的想法很类似 http://www.cnblogs.com/chsword/archive/2010/12/27/searchmodel_1.html
    2011年7月22日 10:02
  • 你好,下面是我从MSDN Library中摘的一段话:

    Lambda 用在基于方法的 LINQ 查询中,作为诸如 WhereWhere 等标准查询运算符方法的参数。

    使用基于方法的语法在 Enumerable 类中调用 Where 方法时(像在 LINQ to Objects 和 LINQ to XML 中那样),参数是委托类型 System.Func<T, TResult>。使用 Lambda 表达式创建委托最为方便。例如,当您在 System.Linq.Queryable 类中调用相同的方法时(像在 LINQ to SQL 中那样),则参数类型是 System.Linq.Expressions.Expression<Func>,其中 Func 是包含至多五个输入参数的任何 Func 委托。同样,Lambda 表达式只是一种用于构造表达式目录树的非常简练的方式。尽管事实上通过 Lambda 创建的对象的类型是不同的,但 Lambda 使得 Where 调用看起来类似。

    并且根据你的错误信息来看,我想你可以在调用Where() 方法之前试试先调用AsEnumerable()这个方法。因为从http://msdn.microsoft.com/zh-cn/library/bb397687(v=vs.90).aspx这里可以看出Where() 在 Enumerable 类型中可以自由使用,所以可能是因为在System.Linq.Queryable这里面不认识Where()方法的缘故。

    希望可以帮到你,

     

    谢谢


    Jackie Sun [MSFT]
    如果您对我们的论坛在线支持服务有任何的意见或建议,请通过邮件告诉我们。
    MSDN 论坛好帮手 立刻免费下载  MSDN 论坛好帮手
    2011年7月27日 6:51
    版主