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