Expression>拼接查询条件


由于项目中经常要用到类似db.students.where多条件查询,因此需要拼接查询条件。

网上搜索大部分出自 Dynamically Composing Expression Predicates 

code如下

 

[csharp]  view plain copy
 
  1. using System;  
  2. using System.Linq;  
  3. using System.Linq.Expressions;  
  4. using System.Collections.Generic;  
  5.    
  6. public static class PredicateBuilder  
  7. {  
  8.   public static Expression<Func<T, bool>> True<T> ()  { return f => true;  }  
  9.   public static Expression<Func<T, bool>> False<T> () { return f => false; }  
  10.    
  11.   public static Expression<Func<T, bool>> Or<T> (this Expression<Func<T, bool>> expr1,  
  12.                                                       Expression<Func<T, bool>> expr2)  
  13.   {  
  14.     var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());  
  15.     return Expression.Lambda<Func<T, bool>>  
  16.           (Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters);  
  17.   }  
  18.    
  19.   public static Expression<Func<T, bool>> And<T> (this Expression<Func<T, bool>> expr1,  
  20.                                                        Expression<Func<T, bool>> expr2)  
  21.   {  
  22.     var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());  
  23.     return Expression.Lambda<Func<T, bool>>  
  24.           (Expression.AndAlso (expr1.Body, invokedExpr), expr1.Parameters);  
  25.   }  
  26. }  

使用代码如下:

 

[csharp]  view plain copy
 
  1. var predicate = PredicateBuilder.True<Gift>();         
  2. predicate = predicate.And(w => w.DataState == DataStateEnum.正常);     
  3. List<Gift> list = db.Gifts.Where(predicate);  

但出现异常:LINQ to Entities 不支持 LINQ 表达式节点类型“Invoke”

 

网上继续搜索,其中一种如下:
List<Gift> list = db.Gifts.Where(predicate.Compile());作者文中提到“他在Linq to sql 上运行正常”,没有验证,

这样确实可以正常工作,但predicate.Compile()后就变成了Func<T, bool>类型,

Entity Framework - Func引起的数据库全表查询

使用 Entity Framework 最要小心的性能杀手就是 —— 不正确的查询代码造成的数据库全表查询。

“将Func类型的变量作为参数传给Where方法进行LINQ查询时,Enitity Framework会产生全表查询,将整个数据库表中的数据加载到内存,然后在内存中根据Where中的条件进一步查询。”  经SQL Server Profiler监测确实如此。

继续找解决办法,找到个Combining two expressions (Expression<func>)

有人回答:

[csharp]  view plain copy
 
  1. //Starting from .net 4.0. There is the ExpressionVistor class which allows you to build expressions that are EF safe.  
  2.   
  3.     public static Expression<Func<T, bool>> AndAlso<T>(  
  4.         this Expression<Func<T, bool>> expr1,  
  5.         Expression<Func<T, bool>> expr2)  
  6.     {  
  7.         var parameter = Expression.Parameter(typeof (T));  
  8.   
  9.         var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[0], parameter);  
  10.         var left = leftVisitor.Visit(expr1.Body);  
  11.   
  12.         var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[0], parameter);  
  13.         var right = rightVisitor.Visit(expr2.Body);  
  14.   
  15.         return Expression.Lambda<Func<T, bool>>(  
  16.             Expression.AndAlso(left, right), parameter);  
  17.     }  
  18.   
  19.   
  20.   
  21.     private class ReplaceExpressionVisitor  
  22.         : ExpressionVisitor  
  23.     {  
  24.         private readonly Expression _oldValue;  
  25.         private readonly Expression _newValue;  
  26.   
  27.         public ReplaceExpressionVisitor(Expression oldValue, Expression newValue)  
  28.         {  
  29.             _oldValue = oldValue;  
  30.             _newValue = newValue;  
  31.         }  
  32.   
  33.         public override Expression Visit(Expression node)  
  34.         {  
  35.             if (node == _oldValue)  
  36.                 return _newValue;  
  37.             return base.Visit(node);  
  38.         }  
  39.     }  

经测试解决问题


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM