簡體   English   中英

創建的謂詞在Linq to Entity Framework Where子句中不起作用

[英]Created predicate doesn't work in Linq to Entity Framework Where clause

我想將謂詞構建邏輯移動到基類中並得到錯誤“LINQ to Entities中不支持LINQ表達式節點類型'調用'”。 我希望能夠連接或有條件地鏈接謂詞中的表達式。

我希望能夠傳入謂詞的一部分,該謂詞對於調用者來說是唯一的屬性名稱( GetFilterPredicate將成為一個通用例程,它將對具有不同屬性名稱並保存相關值的類型進行操作)。

        protected Expression<Func<MyEntity, bool>> GetFilterPredicate(
        PagingParameters pagingParameters,
        Func<MyEntity, DateTime?> terminationDate,
        Func<MyEntity, string> entityID,
        Func<MyEntity, string> name
        )
    {
        Expression<Func<MyEntity, bool>> validFilter = x => true;

        if (pagingParameters.Active == true)
        {
            validFilter = x => terminationDate(x) > DateTime.Now;
        }

        ///more conditions added here

        return validFilter;
    }

    protected List<MyEntity> Query(IQueryable<MyEntity> source)
    {
        var filters = GetFilterPredicate(
            new PagingParameters() { Active = true }
            , i => i.TerminationDate
            , i => i.EntityID
            , i => i.Name
            );

        return source.Where(filters).AsNoTracking().ToList<MyEntity>();
    }

您無法使用委托terminationDate構造新表達式,您需要將terminationDate更改為Expression並使用它來手動構建新表達式。

protected static  Expression<Func<MyEntity, bool>> GetFilterPredicate(
    PagingParameters pagingParameters,
    Expression<Func<MyEntity, DateTime?>> terminationDate,
    Expression<Func<MyEntity, string>> entityID,
    Expression<Func<MyEntity, string>> name
)
{
    Expression<Func<MyEntity, bool>> validFilter = x => true;
    // We need to replace the parameter for all expressions with 
    // a common single parameter. I used the parameter for the default
    // filter but a new Parameter expression would have worked as well.
    // If you don't do this you will get an error (unbound parameter or something like that ) because the parameter  
    // used in the expressions (terminationDate, entityID) will be 
    // different then the parameter used for the new validFilter expression
    var parameterReplacer = new ReplaceVisitor
    {
        NewParameter = validFilter.Parameters.First()
    };

    if (pagingParameters.Active == true)
    {
        validFilter = Expression.Lambda<Func<MyEntity, bool>>(
            Expression.GreaterThan
            (
                parameterReplacer.Visit(terminationDate.Body),
                Expression.Convert(Expression.Property(null, typeof(DateTime), "Now"), typeof(DateTime?))
            ),
            parameterReplacer.NewParameter
        );
    }

    // existing filter && x.EntityId != "A"
    validFilter = Expression.Lambda<Func<MyEntity, bool>>(
            Expression.And(
                validFilter.Body,
                Expression.NotEqual
                (
                    parameterReplacer.Visit(entityID.Body),
                    Expression.Constant("A")
                )
            ),
            parameterReplacer.NewParameter
        );

    return validFilter;
}
/// <summary>
/// Simple Parameter Replacer, will replace the any parameter with the new
/// parameter. You will need to refine this if your expressions have nested 
/// lambda, in that you will need to only replace the top most lambda 
/// parameter, but for simple expressions it will work fine.
/// </summary>
class ReplaceVisitor : ExpressionVisitor
{
    public ParameterExpression NewParameter { get; set; }
    protected override Expression VisitParameter(ParameterExpression node)
    {
        return this.NewParameter;
    }
}

您可以像Titian回答描述的那樣手動執行此操作,但更簡單的方法是使用LinqKit 首先安裝LinqKit nuget包並using LinqKit;添加using LinqKit; , 然后:

// change terminaionDate to Expression<Func<MyEntity, DateTime>>
static Expression<Func<MyEntity, bool>> GetFilterPredicate(Expression<Func<MyEntity, DateTime>> terminationDate) {
    // note Invoke
    Expression<Func<Error, bool>> filter = c => terminationDate.Invoke(c) <= DateTime.Now;
    // note Expand
    return filter.Expand();
}

您可以在上面提供的鏈接上閱讀有關InvokeExpand的內容。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM