如何声明 Linq 表达式变量以便将其作为 dbParameter 处理

Posted

技术标签:

【中文标题】如何声明 Linq 表达式变量以便将其作为 dbParameter 处理【英文标题】:How to declare a Linq Expression variable in order to have it processed as a dbParameter 【发布时间】:2014-08-03 00:03:07 【问题描述】:

我正在尝试针对实体框架(或其他 Linq 提供程序)创建动态查询。

让我用一些示例代码来解释我的问题。

如果我硬编码一个表达式:

var id = 12345;

Expression<Func<ItemSearch, bool>> myLambda = (s) => s.Id == id;

var finalQuery = context.ItemSearch.Where(myLambda);
this.Log((finalQuery as ObjectQuery).ToTraceString());

生成的 SQL 如下所示:

SELECT ...
FROM ViewItemSearch "Extent1"
WHERE "Extent1".ID = :p__linq__0

带有漂亮的:p__linq__0 dbParameter。

如果我创建一个表达式:

var id = 12345;
ParameterExpression param = Expression.Parameter(typeof(ItemSearch), "s");
Expression prop = Expression.Property(param, "Id");
Expression val = Expression.Constant(id);
Expression searchExpr = Expression.Equal(prop, val);

Expression<Func<ItemSearch, bool>> myLambda =  
    Expression.Lambda<Func<ItemSearch, bool>>(searchExpr , param);

var finalQuery = context.ItemSearch.Where(myLambda);
this.Log((finalQuery as ObjectQuery).ToTraceString());

生成的 SQL 如下所示:

SELECT ...
FROM ViewItemSearch "Extent1"
WHERE "Extent1".ID = 12345

没有更多的:p__linq__0 dbParameter,因此 Db 引擎无法缓存查询计划。

我明白是因为我用了

Expression val = Expression.Constant(id);

但我不知道如何绑定变量而不是值。

【问题讨论】:

我觉得你的问题有点令人困惑。如果要动态添加AND逻辑条件,只需声明IQueryable并动态追加.Where(i =&gt; yourPredicate)即可。请参阅:***.com/questions/11189826/… 如果您想应用 OR 逻辑,您将需要这样的方法:albahari.com/nutshell/predicatebuilder.aspx 'or' 和 'and' 表达式工作得很好。问题在于参数的绑定。也许我应该编辑问题并删除结尾。这只是为了上下文。 【参考方案1】:

您需要在编译时创建一个 lambda 以关闭 id 变量,然后您可以在其中获取一个使用的主体以组成更复杂的 lambda:

var id = 12345;
ParameterExpression param = Expression.Parameter(typeof(ItemSearch), "s");
Expression prop = Expression.Property(param, "Id");
Expression<Func<int>> idLambda = () => id;
Expression searchExpr = Expression.Equal(prop, idLambda.Body);

Expression<Func<ItemSearch, bool>> myLambda =
    Expression.Lambda<Func<ItemSearch, bool>>(searchExpr, param);

【讨论】:

以上是关于如何声明 Linq 表达式变量以便将其作为 dbParameter 处理的主要内容,如果未能解决你的问题,请参考以下文章

构建 LINQ 表达式树:如何获取范围内的变量

Firebase Admin SDK 错误:表达式的类型为“void”。将其作为声明放在自己的行中

使用 Linq 表达式进行 C# 动态数据库过滤

如何编写现有的 Linq 表达式

如何从 PostgreSQL 查询转换为 LINQ 或 lambda 表达式

如何在shell脚本中声明和使用布尔变量? POSIX