如何构建使用传入参数构建Expression的存储库方法?

时间:2012-12-14 16:41:53

标签: linq entity-framework expression-trees

我有一个存储库,其中有几个方法在谓词中使用相同的逻辑。

public IList<Loan> GetLoansByCommitmentID(int commitmentID)
{

    var query = this.context.Loans.Where(l => l.CommitmentLoan != null &&
                                         l.CommitmentLoan.CommitmentID == commitmentID && 
                                         (l.LoanStatusTypes == null || (l.LoanStatusTypes.Description != "Invalid")));

    return query.ToList();
}

在上面的代码中,它是最后一个带括号的子表达式:

(l.loanStatusTypes == null || (l.LoanStatusTypes.Description != "Invalid"))

我想将这篇文章移动到存储库的私有方法中,以便它在这种情况下需要一个Loan,并计算为一个布尔值。但是,如果我将此逻辑移动到方法中,则EF不了解如何评估方法调用。在考虑了一下之后,我决定采用这种方法的正确方法是私有存储库方法将Loan作为参数,然后返回一个表达式,用于调用lambda表达式,有点像Expression工厂方法即:

public Expression IsLoanInvalid(Loan l);

有没有人知道这是否会克服EF无法理解方法调用,或者我应该创建自定义ExpressionVisitor还是我应该尝试另一种解决方案?

另外,如果上面提出的解决方案是可行的并且我采用这条路线,我如何构建表达式树以便它使用传入的参数?我已成功实现了一个构建表达式的方法,但到目前为止,将Loan参数传递给我要构建的表达式以返回到调用代码是不成功的。提前谢谢。

1 个答案:

答案 0 :(得分:1)

您可以创建一个变量来保存where where谓词。

public Expression<Func<Loan, bool>> LoanStatus = loan => loan.LoanStatusTypes == null || loan.LoanStatusTypes.Description != "Invalid";

然后再添加一个关闭IQueriable的第二个

public IList<Loan> GetLoansByCommitmentID(int commitmentID)
{    
    var query = this.context.Loans
         .Where(l => l.CommitmentLoan != null && l.CommitmentLoan.CommitmentID == commitmentID)
         .Where(LoanStatus);

    return query.ToList();
}