2016-07-11 32 views
2

のような動的エンティティフレームワークフィルタ式の作成方法フィルタリングのための動的ラムダ式を作成したいと考えています。Expression <Func <T, bool>>

私は少しだけ検索しましたが、子コレクションには役立つものは見つかりませんでした。では、どうやってそのような表現を作ることができますか?

Expression<Func<ORDERS, bool>> filter1 = c => c.ORDER_DETAILS.Any(x => x.PRODUCTS.HEADING.Contains("foo")); 

PS:同様の質問をしましたが、正解を得られませんでした。だから、私が間違っていないなら、この方向から行くことにしました。私の質問について

詳細情報:(How to filter child collection with linq dynamic

私は、ユーザーの要求に対する結果をフィルタリングするためにしようとしています。例えば、 の注文と注文の詳細があり、商品は子供のコレクションです。

ユーザーが製品でフィルタリングしたい場合は、私が原因 ないプロパティまたはフィールドの製品 "のエラーを取得していますタイプに存在する「ICollection1'`

私はこのように私のクエリを書いています。

するvar受注= _uow.Repository() .Query() .Where .INCLUDE( "ORDER_DETAILS") (フー・\ ")" "PRODUCTS.HEADING.ToLowerは()。(\が含まれています")。含める( "ORDER_DETAILS.PRODUCTS") .ToList();だから、このような子コレクションをフィルタリングすることはできないのですか?それともフィルターをかけるのですか?

+0

これを試しましたか?なぜそれは動作しませんでしたか? – Will

+0

@私はそれを動的に作成したいと思います。実際に私はこれに似た質問をしましたが、正解はまだありません。 http://stackoverflow.com/questions/38118300/how-to-filter-child-collection-with-linq-dynamic – Kadir

+0

ダイナミックは非常に広い言葉です。 *動的列名*から不可能*までの範囲です。より具体的に、多分いくつかの例を挙げてください。 – user3185569

答えて

2

はい、可能です。私が使用したアプローチの1つは、検索フィルタと同じ型のオブジェクトを使用します。したがって、 "Bill"の顧客名を検索する場合は、Order.Customer.NameをBillに設定します。そのオブジェクトをメソッドに渡すと、適用可能なすべての検索が適用されます。これを行うには

、検索可能なフィールドのリストを定義することによって開始:

Field<Order>[] Fields; 

は、新しいフィールドを宣言することによって、これらを入力します。

var newField = new Field<Order>(o => o.Customer.Name, true, "Customer Name"); 

「真」パラメータは、それはとして機能することを意味します結果の並べ替えフィールド。

Fieldオブジェクトには、後で式を生成するのに十分な情報が含まれています。それは次のようになります。

public class Field<T> 
{ 
    public Field(Expression<Func<T, object>> field, bool sortField = false, string displayName = null) 
    { 
     //get & validate member 
     MemberExp = field.Body is UnaryExpression ? ((UnaryExpression)field.Body).Operand as MemberExpression 
                : (MemberExpression)field.Body; 

     Field = MemberExp?.Member; 
     if (Field == null) throw new ArgumentException("Field expression is not a member."); 

     //set field type 
     switch (Field.MemberType) 
     { 
      case MemberTypes.Property: 
       PropertyInfo p = (PropertyInfo)Field; 
       FieldType = p.PropertyType; 
       break; 
      case MemberTypes.Field: 
       FieldInfo f = (FieldInfo)Field; 
       FieldType = f.FieldType; 
       break; 
      default: 
       throw new Exception("Unsupported member type detected."); 
     } 

     //store input values 
     FieldExpression = field; 
     SortField = sortField; 
     DisplayName = displayName ?? Field.Name; 
    } 

    public bool SortField { get; set; } 
    public string DisplayName { get; private set; } 
    public MemberExpression MemberExp { get; private set; } 
    public Expression<Func<T, object>> FieldExpression { get; private set; } 
    public Func<T, object> GetValue => FieldExpression.Compile(); 
    public Type FieldType { get; set; } 

    /// <summary> 
    /// Gets the full field name, i.e o => o.Customer.CustomerName returns "Customer.CustomerName" 
    /// </summary> 
    public string UnqualifiedFieldName 
    { 
     get 
     { 
      var stringExp = MemberExp.ToString(); 
      var paramEnd = stringExp.IndexOf('.') + 1; 
      return stringExp.Substring(paramEnd); 
     } 
    } 
} 

あなたはすべての検索可能なフィールドを定義したら、あなたは利用者から収集した(T)検索フィルタに基づいて、検索結果を取得するメソッドを呼び出します。

//get the results in ascending order, 10 items per page, first page 
var results = GetSearchResults(searchFilters, "ASC", 10, 1); 

このメソッドでは、クエリ可能なデータのコレクションが必要です。私はあなたのデータを取得するような方法があると仮定します。context.GetCollection()GetSearchResults方法は次のようになります。

//Returns a filtered dataset based on provided search filters 
//searchFilters is an object T which contains the search filters entered. 
private List<T> GetSearchResults(T searchFilters, string sortDir = "ASC", int pageSize, int currentPage) 
{ 
    IQueryable<T> searchResults = context.GetCollection(); //get your data context here 

    var filterExpressions = new List<Expression<Func<T, bool>>>(); 

    //Add filters 
    foreach (var field in Fields) 
    { 
     //try to get the search value, ignoring null exceptions because it's much harder 
     //to check for null objects at multiple levels. Instead the exception tells us there's 
     //no search value 
     string searchValue = null; 
     try 
     { 
      searchValue = field.GetValue(searchFilters)?.ToString(); 
     } 
     catch (NullReferenceException) { } 
     if (string.IsNullOrWhiteSpace(searchValue)) continue; 

     //shared expression setup 
     ParameterExpression param = field.FieldExpression.Parameters.First(); 
     Expression left = field.FieldExpression.Body; 
     ConstantExpression right = Expression.Constant(searchValue); 
     Expression body = null; 

     //create expression for strings so we can use "contains" instead of "equals"   
     if (field.FieldType == typeof(string)) 
     { 
      //build the expression body 
      MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });      
      body = Expression.Call(left, method, right); 
     } 
     else 
     { //handle expression for all other types  
      body = Expression.Equal(left, right); 
     } 

     //finish expression 
     Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(body, param); 
     filterExpressions.Add(lambda); 
    } 

    //apply the expressions 
    searchResults = filterExpressions.Aggregate(searchResults, (current, expression) => current.Where(expression)); 

    //get sort field 
    Field<T> sortField = Fields.FirstOrDefault(f => f.SortField); 
    searchResults = searchResults.OrderBy($"{sortField.UnqualifiedFieldName} {sortDir}");                   

    // Get the search results 
    int count = searchResults.Count(); 
    int maxPage = count/pageSize; 
    if (maxPage * pageSize < count) maxPage++; 
    if (currentPage > maxPage) currentPage = maxPage; 
    int skip = Math.Max(0, (filters.page - 1) * pageSize); 
    int display = Math.Max(0, Math.Min(count - skip, pageSize)); 
    return searchResults.Skip(skip).Take(display).ToList(); 
}  

をこの方法では、条件に一致する式を作成し、データセットに適用するには、あなたのField[]配列を使用しています。

私はそれが助けてくれることを願っています!ご質問がある場合はお知らせください。

関連する問題