也说Linq动态条件查询

简介:

 1,构造表达式树

None.gif     private Expression<Func<Blog,  bool>> getCondition()
ExpandedBlockStart.gif     {
InBlock.gif        Expression<Func<Blog, bool>> expression = blog => true;
InBlock.gif
InBlock.gif        if (!String.IsNullOrEmpty(Request["BlogClassID"]))
ExpandedSubBlockStart.gif        {
InBlock.gif            int blogClassID;
InBlock.gif            if (Int32.TryParse(Request["BlogClassID"], out blogClassID))
ExpandedSubBlockStart.gif            {
InBlock.gif                Expression<Func<Blog, bool>> e2 = blog => blog.BlogClass == null;
InBlock.gif                var invokedExpr = Expression.Invoke(e, expression.Parameters.Cast<Expression>());
InBlock.gif
InBlock.gif                expression = Expression.Lambda<Func<Blog, bool>>(Expression.And(expression.Body, invokedExpr), expression.Parameters);
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        return expression;
ExpandedBlockEnd.gif    }
主查询是这个样子:
None.gif        var result =  new DongBlogDataContext().Blogs.Where(getCondition());
None.gif
因为根据SQL追踪,生成SQL类似:
None.gif SELECT  [ t0 ]. [ BlogID ][ t0 ]. [ ChannelID ][ t0 ]. [ BlogClassID ][ t0 ]. [ Title ][ t0 ]. [ Content ][ t0 ]. [ Tag ][ t0 ]. [ CreateDateTime ]
None.gif FROM  [ dbo ]. [ Blog ]  AS  [ t0 ]
None.gif WHERE  [ t0 ]. [ BlogClassID ]  IS  NULL

这种方法是实质是合并Lamba表达式,也就是这三句:

None.gif                Expression<Func<Blog,  bool>> e = blog => blog.BlogClass ==  null;
None.gif                var invokedExpr = Expression.Invoke(e, expression.Parameters.Cast<Expression>());
None.gif
None.gif                expression = Expression.Lambda<Func<Blog,  bool>>(Expression.And(expression.Body, invokedExpr), expression.Parameters);
None.gif

如果每个条件合并都这么写会很麻烦,幸好已经有人给写好的辅助类:http://www.albahari.com/expressions/

None.gif using System;
None.gif using System.Linq;
None.gif using System.Linq.Expressions;
None.gif using System.Collections.Generic;
None.gif 
None.gif public  static  class PredicateBuilder
ExpandedBlockStart.gif {
ExpandedSubBlockStart.gif  public static Expression<Func<T, bool>> True<T> ()  return f => true;  }
ExpandedSubBlockStart.gif  public static Expression<Func<T, bool>> False<T> () return f => false; }
InBlock.gif 
InBlock.gif  public static Expression<Func<T, bool>> Or<T> (this Expression<Func<T, bool>> expr1,
InBlock.gif                                                      Expression<Func<T, bool>> expr2)
ExpandedSubBlockStart.gif  {
InBlock.gif    var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
InBlock.gif    return Expression.Lambda<Func<T, bool>>
InBlock.gif          (Expression.Or (expr1.Body, invokedExpr), expr1.Parameters);
ExpandedSubBlockEnd.gif  }

InBlock.gif 
InBlock.gif  public static Expression<Func<T, bool>> And<T> (this Expression<Func<T, bool>> expr1,
InBlock.gif                                                       Expression<Func<T, bool>> expr2)
ExpandedSubBlockStart.gif  {
InBlock.gif    var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
InBlock.gif    return Expression.Lambda<Func<T, bool>>
InBlock.gif          (Expression.And (expr1.Body, invokedExpr), expr1.Parameters);
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif

这个类可以用于Expression<Func<T, bool>>类型的表达式的合并了。具体用法参看http://www.albahari.com/expressions/http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1745163&SiteID=1

2,构造Query
同第一种查询更好的写法:

None.gif     private IQueryable<Blog> getQuery()
ExpandedBlockStart.gif     {
InBlock.gif        IQueryable<Blog> query = new DongBlogDataContext().Blogs;
InBlock.gif        if (!String.IsNullOrEmpty(Request["BlogClassID"]))
ExpandedSubBlockStart.gif        {
InBlock.gif            int blogClassID;
InBlock.gif            if (Int32.TryParse(Request["BlogClassID"], out blogClassID))
InBlock.gif                query = query.Where<Blog>(blog => blog.BlogClass == null);
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        return query.OrderByDescending(blog => blog.CreateDateTime);
ExpandedBlockEnd.gif    }

主查询

None.gifvar result = getQuery();

生成的SQL和第一个完全相同。

园子里相关讨论还有
http://www.cnblogs.com/neuhawk/archive/2007/07/07/809585.html
http://www.cnblogs.com/blusehuang/archive/2007/07/13/816970.html
还可参考:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1706161&SiteID=1


本文转自冬冬博客园博客,原文链接:http://www.cnblogs.com/yuandong/archive/2007/07/17/820888.html ,如需转载请自行联系原作者

相关文章
|
.NET
LINQ 如何动态创建 Where 子查询
还是那句话,十年河东,十年河西,莫欺少年穷! 学无止境,精益求精... 今天探讨下如何构造动态的LINQ子查询 LINQ,相信大家都写过,很简单,下面以一个基本的范例说明下: namespace ConsoleMe { class Program {...
1688 0
|
.NET 开发框架 存储
|
机器学习/深度学习 .NET
|
SQL .NET 开发框架
|
.NET 索引 开发框架