2017-02-18 7 views
1

エンティティプロパティをLINQ式のパラメータとして渡すにはどうすればよいですか?私はこのようにそれを使用することになりますエンティティプロパティをLINQ式のパラメータとして渡すにはどうすればよいですか?

public DropdownFilter(WhatTypeHere? ABC) 
{ 
    // I want to store a selected property here 
    // ABC must be a property of TEntity 
    this.ABC = ABC; 
} 

// I want the class to encapsulate a LINQ query and just parametrize it with a property 
public override IQueryable<TEntity> Filter(IQueryable<TEntity> filteredEntityCollection, string value) 
{ 
    // ABC is a property of TEntity 
    return filteredEntityCollection.Where(this.ABC == value); 
} 

new DropdownFilter<Invoice>(invoice => invoice.SomeProperty); 

私はすでに、パラメータのExpression<Func<TEntity, string>>種類で試してみましたが、それはうまくいきませんでした。文句を言っている

The LINQ expression node type 'Invoke' is not supported in LINQ to Entities. 

答えて

1

LINQ式を手動で構築する必要があります。まず第一に、私はあなたがフィルターに渡すプロパティと値の種類のタイプを指定することになる、あなたのクラスに2つ目の一般的なパラメータを追加します。

public class DropdownFilter<TEntity, TProperty> 

次のあなたは、このフィルタクラスのコンストラクタにプロパティセレクタ式を渡す必要があります:

private PropertyInfo propertyInfo; 

public DropdownFilter(Expression<Func<TEntity, TProperty>> propertySelector) 
{ 
    this.propertyInfo = (PropertyInfo)((MemberExpression)propertySelector.Body).Member; 
} 

そして最後には、指定したプロパティの値が与えられたことにより、照会可能フィルタリングするラムダ式を作成:

public IQueryable<TEntity> Filter(
    IQueryable<TEntity> filteredEntityCollection, TProperty value) 
{ 
    var param = Expression.Parameter(typeof(TEntity), "p"); 

    var lambda = Expression.Lambda<Func<TEntity, bool>>(    
     Expression.Equal(
      Expression.Property(param, propertyInfo), 
      Expression.Constant(value) 
     ), param); 

    return filteredEntityCollection.Where(lambda); 
} 

用途:

var filter = new DropdownFilter<Invoice, string>(i => i.ABC); 
var result = filter(db.Invoices, "foo"); // strongly-typed parameter here 

コンストラクタに渡されたプロパティセレクタ式の検証を追加します。それがMemberExpressionかどうかを確認する必要があります。また、プリミティブ型のプロパティだけをサポートするために、プロパティ型を検証できます。

+1

これは素晴らしいことですが、それはうまくいくでしょうが、 'TProperty'を上向きに伝播する方法を理解する前にそれを使うことはできません。すべての' filters'が基本クラスから継承しているので、これは別のオブジェクトのリストプロパティとして使用されています... –

+0

@HristoYankovまあ、TPropertyを削除して、以前のように 'string'を使うことができます(しかし、' propertyInfo.PropertyType'をstringにチェックしてください)か、 'object'を値として、それを' Expression.Convert(Expression.Constant(value)、propertyType) 'でプロパティ型に変換します。 –

関連する問題