当前位置 > 首页 > Asp.net

PredicateBuilder 对 ADO.Net Entity Framework 支持的改进

9/7/2012 10:23:00 AM来源:Asp.net

曾几何时,网络上曾经大传 PredicateBuilder 用于拼接两个 Lambda 表达式树。在对内存数据的筛选上面,其简洁方便的操作大放异彩,但是对数据库操作的不支持,一直是其硬伤。PredicateBuilder 拼接表达式的过程中,产生的 Invoke 表达式无法翻译成 SQL 语句,这是其根本原因。另外,Invoke 表达式编译后,形成的委托调用委托的方式,也是对性能的一种损耗。

 

当然,也有很多人对其做过改造,不过给人的感觉,总不是那么完美。以前,因为种种原因,我们不得不忍受这种问题。前几天,由于工作中用到了 Entity Framework 和动态拼接 Lambda 表达式树,为了避免全表查询的尴尬,硬着头皮研究改造 PredicateBuilder —— 各种纠结。还好,了解透彻原理后就很简单了。期间,用到了下面这个测试类:

public class Person{    public int ID { get; set; }    public string Name { get; set; }}

 

这里先说一下要达到的目的:

两个表达式:

Expression<Func<Person, bool>> a = p => p.ID == 3;Expression<Func<Person, bool>> b = c => c.Name == "张三";

拼接之后,想要达成如下形式:

Expression<Func<Person, bool>> x = y => y.ID == 3 && y.Name == "张三";

原始 PredicateBuilder 用的是 Invoke 表达式,也就是说没有解析待拼接的表达式。我们可以解析一下,看看能否达到效果。

 

首先来看相同点:

表达式 a :根是一个相等判断的二元表达式,其左子树是属性的调用的表达式,右子树是一个数字常量表达式。

表达式 b :根是一个相等判断的二元表达式,其左子树是属性的调用的表达式,右子树是一个数字常量表达式。

下面看不同:

表达式 a 参数名字是 p ,表达式 b 参数名字是 c —— 两者参数的名称不同,但是类型是相同的。

 

对于目标表达式,这里我第一印象是把右边表达式的参数,改成左边的,然后把左右两边表达式的 Body 拼接,加上左边的参数,这就是目标表达式树。经过分析,这种做法是可行的,下面上代码,代码不解释:

/// <summary>/// 谓词表达式构建器/// </summary>public static class PredicateBuilder{    #region Expression Joiner    /// <summary>    /// 创建一个值恒为 <c>true</c> 的表达式。    /// </summary>    /// <typeparam name="T">表达式方法类型</typeparam>    /// <returns>一个值恒为 <c>true</c> 的表达式。</returns>    public static Expression<Func<T, bool>> True<T>() { return p => true; }    /// <summary>    /// 创建一个值恒为 <c>false</c> 的表达式。    /// </summary>    /// <typeparam name="T">表达式方法类型</typeparam>    /// <returns>一个值恒为 <c>false</c> 的表达式。</returns>    public static Expression<Func<T, bool>> False<T>() { return f => false; }    /// <summary>    /// 使用 Expression.OrElse 的方式拼接两个 System.Linq.Expression。    /// </summary>    /// <typeparam name="T">

  • 一些不是很常用的SQL语句

    9/20/2009 5:26:00 PM

    摘要: [代码] ----------------------------------------------------------------------------------------

  • asp.net mvc 2.0+Silverlight播放器开发的TeamVideo视频播放网站--系列2

    9/4/2010 7:38:00 PM

    作者: Nic Pei 发表于 2010-09-04 18:45 原文链接 阅读: 41 评论: 0 这几天抽空写第二部分。很高兴今天能够和大家分享下。我这是个asp.net mvc的新

  • 用托管代码调用 Windows 7 任务栏的新功能

    2/1/2009 11:01:00 PM

    摘要: 本文以C#和任务栏进度条为例介绍了如何用托管代码调用Windows7的新特性。 阅读全文 -------------------------- 新闻: 英知名网站评10大鼓舞人心IT事

  • [MSSQL]添加数据到数据库,ADO.NET入门之前!

    10/25/2011 6:05:00 PM

    建一个表,主键为varchar型,从00000 开始,每一条加1 MSSQL代码以下: declare @autoid varchar ( 20 ), @name varc

  • Windows XP SP4升级包或于五年后问世?

    5/23/2009 5:56:00 PM

    早在2006年年中Windows XP SP3远未发布的时候,就有传闻说微软还会为这套经典操作系统推出第四个SP服务包,但此后就再也没有更多消息。在Windows XP RTM大限迫近的时候,ZDN

  • 我也搞了个皮肤

    4/2/2007 4:10:00 AM

    摘要: 受Cure的水滴皮肤影响,我也给自己做了一个。 还通过角本增加了以下功能: 1.滚动显示的子标题 2.统计信息 3.贴子声明 4.在菜单栏加MSN联系的快捷键 阅读全文

  • js动态代理

    5/23/2009 1:37:00 AM

    最近公司的产品陆续跟其他网站有合作,麻烦的是每个网站都有个性化的需求,有的需要自己的logo,有的需要定制的广告。 例如默认我们显示的是Google广告 http://www.wangcha

  • 当心异步刷新后的脚本文件加载

    4/9/2007 8:47:00 AM

    摘要: 如果第一次异步刷新在加载脚本时发起了另一个异步刷新,第二次异步刷新可能就会不受我们控制地被中断了。 阅读全文 Jeffrey Zhao 2007-04-09 08:43 发表评论

  • [讨论] 关于插件框架式程序的讨论

    3/31/2007 6:30:00 PM

    摘要: 插件框架式程序已经不是一个新话题了,发现大家在平日讨论或者在大家的文章中都讨论到了通讯协议、版本控制等。但是我们的插件也是有可能发生错误,而对于插件内发生的错误如果没有进行处理的话,就会导致

  • Building mobile web site with ASP.NET MVC and jQuery Mobile

    10/27/2010 11:41:00 AM

    jQuery Mobile is unified UI system that will work on all popular mobile device platforms. Currentl