2014-01-10 26 views
0

我想知道我該怎麼做? 事實是我有一個對象與一個搜索條件(一些領域來搜索哪個意味着條件)。我需要根據條件構建查詢,但是它與AND一起加入。 這是我有:實體框架構建OR並傳遞到Where

public class SearchCriteria 
{ 
    public SearchCriteria() 
    { 
     this.Theme = new HashSet<int>(); 
    } 

    public string KeyWord { get; set; } 
    public bool? ChildrenFirstCycle { get; set; } 
    public bool? ChildrenSecondCycle { get; set; } 
    public bool? Primary { get; set; } 
    public bool? Secondary { get; set; } 
    public bool? BachelorArts { get; set; } 
    public bool? BachelorHumanities { get; set; } 
    public bool? BachelorScience { get; set; } 
    public bool? University { get; set; } 
    public bool? MediumLevelCycle { get; set; } 
    public bool? HighLevelCycle { get; set; } 
    public int? DistrictID { get; set; } 
    public int? CountyID { get; set; } 
    public int? MunicipalID { get; set; } 
    public ICollection<int> Theme { get; set; } 
} 

    public IEnumerable<School> GetAllEscuelasBySearchCriteria(SearchCriteria searchCriteria) 
    { 
     var Query = this._repository.Retrieve(); 

     if (!string.IsNullOrWhiteSpace(searchCriteria.KeyWord)) 
     { 
      Query = Query.Where(p => p.Name.Contains(searchCriteria.KeyWord) || p.Grade.Contains(searchCriteria.KeyWord) || p.Email.Contains(searchCriteria.KeyWord) || p.Address.Contains(searchCriteria.KeyWord) || p.Code.Contains(searchCriteria.KeyWord)); 
     } 

     //Rest of condition 
     if (RestConditions) 
     { 
      Query = Query.Where(p=> REST CONDITIONS); 
     } 

     //I need to create a list of func expression and add each expression pass the condition and then a foreach and do an OR for all in List of FUNC 

     if (searchCriteria.InfantilFirstCycle.HasValue && searchCriteria.InfantilFirstCycle.Value != false) 
     { 
      Query = Query.Where(p => (p.value1 > 0 || p.value2 > 0 || p.value3 > 0)); 
     } 
     if (searchCriteria.InfantilSecondCycle.HasValue && searchCriteria.InfantilSecondCycle.Value != false) 
     { 
      Query = Query.Where(p => (p.value4 > 0 || p.value5 > 0 || p.value6 > 0)); 
     } 
     if (searchCriteria.Primary.HasValue && searchCriteria.Primary.Value != false) 
     { 
      Query = Query.Where(p => (p.value7 > 0 || p.value8 > 0 || p.value9 > 0 || p.value10 > 0 || p.value11 > 0 || p.value13 > 0 || p.value14 > 0)); 
     } 

     return Query.Distinct().OrderBy(c=>c.Name).ToList(); 
    } 
+0

我有這個確切的問題,並最終使用動態linq.https://github.com/kahanu/System.Linq.Dynamic – Mansfield

+0

我試過但說基地{System.Exception} = {「在LINQ to Entities不支持LINQ表達式節點類型'Invoke'。」} – user2528557

回答

1

檢查出這個NuGet包使上IQueryable的搜索擴展。

https://www.nuget.org/packages/NinjaNye.SearchExtensions/

它可以讓你做到以下幾點:

var query = this._repository.Retrieve(); 

query = query.Search(searchCriteria.KeyWord, p => p.Name, p => p.Email, p => p.Address, p => p.Code) 
      .Where(p => searchCriteria.InfantilFirstCycle == true && (p.value1 > 0 || p.value2 > 0 || p.value3 > 0)) 
      .Where(p => searchCriteria.InfantilSecondCycle == true && (p.value4 > 0 || p.value5 > 0 || p.value6 > 0)) 
      .Where(p => searchCriteria.Primary == true && (p.value7 > 0 || p.value8 > 0 || p.value9 > 0 || p.value10 > 0 || p.value11 > 0 || p.value13 > 0 || p.value14 > 0)) 

return query.Distinct().OrderBy(c=>c.Name).ToList(); 

源代碼是在這裏以及一些示例用法:

https://github.com/ninjanye/SearchExtensions

對於額外的where子句,您可以調整搜索擴展代碼以滿足您的需求。類似下面的內容將啓用以下語法:

var query = this._repository.Retrieve();  
    query = query.Search(searchCriteria.KeyWord, 
         p => p.Name, 
         p => p.Email, 
         p => p.Address, 
         p => p.Code) 

    if(searchCriteria.InfantilFirstCycle == true) 
    { 
     query = query.IntGreaterThan(0, p => p.value1, p => p.value2, p => p.value3);    
    } 

    if(searchCriteria.InfantilSecondCycle == true) 
    { 
     query = query.IntGreaterThan(0, p => p.value4, p => p.value5, p => p.value6);    
    } 

    if(searchCriteria.Primary == true) 
    { 
     query = query.IntGreaterThan(0, p => p.value7, p => p.value8, p => p.value9, p => p.value10, p => p.value11, p => p.value13, p => p.value14); 
    } 

    return query.Distinct().OrderBy(c=>c.Name).ToList(); 

以下是啓用上述內容的代碼。 (請注意,這已經被寫入未經測試,可能需要的調整)

public static class Extensions 
{ 
    public static IQueryable<T> IntGreaterThan<T>(this IQueryable<T> source, int greaterThanValue, params Expression<Func<T, int>>[] integerProperties) 
    { 
     //Variable to hold merged 'OR' expression 
     Expression orExpression = null; 

     //Retrieve first parameter to use accross all expressions 
     var singleParameter = integerProperties[0].Parameters.Single(); 

     //Create a constant to represent the search term 
     ConstantExpression greaterThanExpression = Expression.Constant(greaterThanValue) 

     //Build a contains expression for each property 
     foreach (var intProperty in integerProperties) 
     { 
      //Syncronise single parameter accross each property 
      var swappedParamExpression = SwapExpressionVisitor.Swap(intProperty, intProperty.Parameters.Single(), singleParameter); 

      //Build expression to represent x.[propertyX] > greaterThanValue 
      var expression = BuildGreaterThanExpression(swappedParamExpression, greaterThanExpression); 

      //Add contains expresion to the existing expression 
      orExpression = BuildOrExpression(orExpression, expression); 
     }  

     var completeExpression = Expression.Lambda<Func<T, bool>>(orExpression, singleParameter); 
     return source.Where(completeExpression); 
    } 

    private static BinaryExpression BuildGreaterThanExpression<T>(Expression<Func<T, int>> intProperty, ConstantExpression greaterThanExpression) 
    { 
     return Expression.GreaterThan(intProperty.Body, greaterThanExpression); 
    } 

    /// <summary> 
    /// Connect to expressions using the OrElse expression 
    /// </summary> 
    private static Expression BuildOrExpression(Expression existingExpression, Expression expressionToAdd) 
    { 
     if (existingExpression == null) 
     { 
      return expressionToAdd; 
     } 

     //Build 'OR' expression for each property 
     return Expression.OrElse(existingExpression, expressionToAdd); 
    } 
} 


internal class SwapExpressionVisitor : ExpressionVisitor 
{ 
    private readonly Expression from, to; 
    private SwapExpressionVisitor(Expression from, Expression to) 
    { 
     [email protected] = @from; 
     this.to = to; 
    } 

    public static Expression<T> Swap<T>(Expression<T> lambda, Expression from, Expression to) 
    { 
     return Expression.Lambda<T>(
      Swap(lambda.Body, from, to), lambda.Parameters); 
    } 

    private static Expression Swap(Expression body, Expression from, Expression to) 
    { 
     return new SwapExpressionVisitor(from, to).Visit(body); 
    } 

    public override Expression Visit(Expression node) 
    { 
     return node == [email protected] ? this.to : base.Visit(node); 
    } 
}  
+0

正是我想要的。真棒套餐。 – JonE