将方法转换为Linq表达式以进行查询

DLe*_*Leh 5 c# linq expression-trees linq-to-sql

在我们的应用程序中,我们希望为数据库中的各种条件提供标准方法.例如,我们有不同类型的事务,我们希望创建标准方法以在其他查​​询中检索它们.但是,这给了我们错误:

方法''没有支持的SQL转换

该方法可能如下所示:

public static bool IsDividend(this TransactionLog tl)
{
    return tl.SourceTypeID == (int)JobType.Dividend || tl.SourceTypeID == (int)JobType.DividendAcct;
}
Run Code Online (Sandbox Code Playgroud)

要这样使用:

var dividends = ctx.TransactionLogs.Where(x => x.IsDividend());
Run Code Online (Sandbox Code Playgroud)

当然,如果我将逻辑从子句复制IsDividend()Where子句中,这样可以正常工作,但是我最终会在很多地方复制这个逻辑,并且如果逻辑发生变化则很难跟踪.

我想如果我将它转换为这样的表达式它可以工作,但这不是一个优秀的设置,因为能够使用方法:

public Expression<Func<TransactionLog, bool>> IsDividend = tl => tl.SourceTypeID == (int)JobType.Dividend || tl.SourceTypeID == (int)JobType.DividendAcct;

var dividends = ctx.TransactionLogs.Where(IsDividend);
Run Code Online (Sandbox Code Playgroud)

有没有办法迫使Linq将方法评估为表达式?或者将方法调用"转换"为linq查询中的表达式?像这样的东西:

var dividends = ctx.TransactionLogs.Where(tl => ToExpression(tl.IsDividend));
Run Code Online (Sandbox Code Playgroud)

我们在我们的应用程序中使用Linq-to-SQL.

Tse*_*eng 1

好吧,拥有包含表达式的静态属性对我来说似乎很好。

使其与方法一起使用的唯一方法是创建一个返回此表达式的方法,然后在其中调用它:

public class TransactionLog 
{
    Expression<Func<TransactionLog, bool>> IsDividend() {
        Expression<Func<TransactionLog, bool>> expression = tl => tl.SourceTypeID == (int)JobType.Dividend || tl.SourceTypeID == (int)JobType.DividendAcct;
        return expression;
    }
}

public class TransactionLogExtension
{
    Expression<Func<TransactionLog, bool>> IsDividend(this TransactionLog log) {
        Expression<Func<TransactionLog, bool>> expression = tl => tl.SourceTypeID == (int)JobType.Dividend || tl.SourceTypeID == (int)JobType.DividendAcct;
        return expression;
    }
}
Run Code Online (Sandbox Code Playgroud)

并通过使用它

var dividends = ctx.TransactionLogs.Where(TransactionLog.IsDividend());
Run Code Online (Sandbox Code Playgroud)

或作为扩展方法

var dividends = ctx.TransactionLogs.Where(x.IsDividend());
Run Code Online (Sandbox Code Playgroud)

但它们都不起作用,var dividends = ctx.TransactionLogs.Where(x => x.IsDividend());因为x => x.IsDividend();它本身是一个表达式树,并且您的数据库提供程序无法将“IsDividend”转换为 SQL 语句。

但其他两个选项至少允许您传入参数(如果您将表达式存储为实例或静态属性,则这不起作用)。