在我们的应用程序中,我们希望为数据库中的各种条件提供标准方法。例如,我们有不同类型的事务,我们希望创建标准方法以在其他查询中检索它们。但是,这给了我们错误:
方法''没有受支持的SQL翻译
该方法可能如下所示:
public static bool IsDividend(this TransactionLog tl)
{
return tl.SourceTypeID == (int)JobType.Dividend || tl.SourceTypeID == (int)JobType.DividendAcct;
}
如此使用:
var dividends = ctx.TransactionLogs.Where(x => x.IsDividend());
当然,如果我将逻辑从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);
有没有办法迫使Linq将方法评估为表达式?或者转换&#34;转换&#34;该方法调用linq查询中的表达式?像这样:
var dividends = ctx.TransactionLogs.Where(tl => ToExpression(tl.IsDividend));
我们在我们的应用程序中使用Linq-to-SQL。
答案 0 :(得分:1)
包含表达式的静态属性对我来说似乎很好。
使其与Method一起使用的唯一方法是创建一个返回此表达式的方法,然后在其中调用它:
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;
}
}
并通过
使用它var dividends = ctx.TransactionLogs.Where(TransactionLog.IsDividend());
或作为扩展方法
var dividends = ctx.TransactionLogs.Where(x.IsDividend());
但它都不适用于var dividends = ctx.TransactionLogs.Where(x => x.IsDividend());
,因为x => x.IsDividend();
本身就是一个表达式树,而您的数据库提供商无法翻译&#34; IsDividend&#34;进入SQL语句。
但是其他两个选项至少允许您传入参数(如果将表达式存储为实例或静态属性,则这些参数不起作用)。
答案 1 :(得分:0)
我认为LINQ to SQL并不完全支持常见和内置函数。 (至少EF没有这样做)。而且 - 当它处理用户定义的方法时。我预测,除非在枚举后调用它(ToList或类似方法),否则带表达式的变体将与使用方法调用的变量一样下降。我建议保持1)存储过程在服务器之间的平衡,2)在C#中Where
子句中硬编码的常见条件,3)在C#中生成表达式树。所有这些都是相对复杂的,当然(在我看来,没有简单而通用的解决方案)。
答案 2 :(得分:0)
尝试使用扩展方法,如下所示:
public static class TransactionLogExtensions {
public static IQueryable<TransactionLog> OnlyDividends(this IQueryable<TransactionLog> tl)
{
return tl.Where(t=>t.SourceTypeID == (int)JobType.Dividend || t.SourceTypeID == (int)JobType.DividendAcct);
}
}
这样称呼:
var dividends=db.TransactionLogs.OnlyDividends();
或
var dividends=db.TransactionLogs.OnlyDividends().OrderBy(...);
答案 3 :(得分:-1)
对于此方案,您可以使用Func。 Linq对那些非常好。 以下是在Linq查询中使用Func的简单示例。随意修改和使用。
Func<int,bool> isDivident = x => 3==x;
int[] values = { 3, 7, 10 };
var result = values.Select (isDivident );