2016-08-27 42 views
4

Entity FrameworkでOrderBy式を動的に作成する方法については、this answerを見てきました。しかし、私は動的なWhere式を構築したいと思います。Where ExpressionをEntity Frameworkで動的に構築するには?

public IEnumerable<InventoryItem> GetAll(string filterBy, object value) 
{ 
    var results = new List<InventoryItem>(); 
    using (var db = new InventoryDb()) 
    { 
    if (QueryHelper.PropertyExists<InventoryItem>(filterBy)) 
    { 
     var query = db.rri_InventoryItems.WhereByProperty(filterBy, value); 

     foreach(var item in query.Where(expr)) 
     { 
     results.Add(ConvertItem(item)); 
     } 
    }    
    } 
    return results; 
} 

フィルタリングするプロパティとabオブジェクトの値を渡します。 Queryableには2つのメソッドがあり、どちらも2つのパラメーターを取るため、どちらが適切かはわかりません。

そして、この時点で私は少し失われてしまいます。私はどのようにオリジナルをリファクタリングするか分からないOrderByProertyメソッドを提供するWhereByPropertyを提供する。私がここにいるものが完全に間違っていることは分かっています。私はそれをどうするか分からない。

理想的には、私ももっと論理積またはオペレータとクエリを構築するために使用することができ、オブジェクトのコレクションを提供することにより、これを拡張したいと思います。

答えて

3

Queryableには2つのパラメータがあり、どちらが2つのパラメータを取るかという2つの方法があります。どちらが適切なのかはわかりません。

Expression<Func<T, bool>> predicateを受け取るものが必要です。私はあなたはそれが何をするかを理解するために、コードをステップオーバーすることができますので、このような方法でそれを書くことを試みた

public static partial class QueryableExtensions 
{ 
    public static IQueryable<T> WhereEquals<T>(this IQueryable<T> source, string member, object value) 
    { 
     var item = Expression.Parameter(typeof(T), "item"); 
     var memberValue = member.Split('.').Aggregate((Expression)item, Expression.PropertyOrField); 
     var memberType = memberValue.Type; 
     if (value != null && value.GetType() != memberType) 
      value = Convert.ChangeType(value, memberType); 
     var condition = Expression.Equal(memberValue, Expression.Constant(value, memberType)); 
     var predicate = Expression.Lambda<Func<T, bool>>(condition, item); 
     return source.Where(predicate); 
    } 
} 

:ここ

はあなたが動的に(T item) => item.Property == valueに似た述語を構築する方法です。いくつかの説明が必要な場合があります唯一の行は次のようになります。

var memberValue = member.Split('.').Aggregate((Expression)item, Expression.PropertyOrField); 

これは、あなたがこのような機能を必要としない場合などobj.Prop1.Prop2のようなネストされたプロパティを処理する簡単な方法で、あなたは単に代わりにこれを使用することができます。

var memberValue = Expression.PropertyOrField(item, member); 
1

まだネストされたプロパティは必要ありませんでした(まだ)。あなたのコードを少し修正して、これが動作しているようにしてください:

public static IQueryable<T> WhereEquals<T>(
     this IQueryable<T> source, string propertyName, object value) 
    { 
     if (typeof(T).GetProperty(propertyName, BindingFlags.IgnoreCase | 
      BindingFlags.Public | BindingFlags.Instance) == null) 
     { 
      return null; 
     } 

     ParameterExpression parameter = Expression.Parameter(typeof(T), "item"); 
     Expression whereProperty = Expression.Property(parameter, propertyName); 
     Expression constant = Expression.Constant(value); 
     Expression condition = Expression.Equal(whereProperty, constant); 
     Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(condition,parameter); 
     return source.Where(lambda); 
    } 
関連する問題