2017-02-18 70 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表達式。首先,我想第二個泛型參數添加到您的類,這將指定的屬性和價值型類型,你會傳遞給過濾:

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'是字符串),或者你可以使用'object'作爲值,並通過'Expression.Convert(Expression.Constant(value),propertyType)將其轉換爲屬性類型' –

相關問題