gpt4 book ai didi

c# - 动态构建 LINQ 查询 - 强制使用 sp_executesql 而不是原始查询

转载 作者:太空宇宙 更新时间:2023-11-03 20:55:17 24 4
gpt4 key购买 nike

我需要动态构建查询(实体类有 30 多个属性,我想避免使用多个 if 语句)。我使用反射和表达式树解决了这个问题(如果指定了某些搜索条件,则按属性迭代并附加谓词)。问题在于它会生成原始 SQL 脚本。

例子

SELECT 
[Extent1].[ProductId] AS [ProductId],
[Extent1].[ManufacturerId] AS [ManufacturerId],
[Extent1].[Title] AS [Title]
FROM [dbo].[Products] AS [Extent1]
WHERE 3 = [Extent1].[ManufacturerId]

我需要使用 sp_executesql 过程获取查询(重新执行相同的查询执行计划)。

exec sp_executesql N'SELECT 
[Extent1].[ProductId] AS [ProductId],
[Extent1].[ManufacturerId] AS [ManufacturerId],
[Extent1].[Title] AS [Title]
FROM [dbo].[Products] AS [Extent1]
WHERE [Extent1].[ManufacturerId] = @p__linq__0',N'@p__linq__0 int',@p__linq__0=3

原来问题出在下面的方法中。它使用 Expression.Constant 来创建 Expression 对象。我不知道应该用什么来代替它。

public static Expression<Func<TItem, bool>> PropertyEqual<TItem, TValue>(
this PropertyInfo property, TValue value)
{
var param = Expression.Parameter(typeof(TItem));
var body = Expression.Equal(Expression.Property(param, property),
Expression.Constant(value, typeof(TValue)));
return Expression.Lambda<Func<TItem, bool>>(body, param);
}

我该如何解决这个问题?

最佳答案

为了让 EF 使用参数而不是常量值,您需要引入一个闭包(类似于 C# 编译器对编译时表达式所做的)。

一种方法是创建匿名类型并绑定(bind)它的属性:

var closure = new { value };
var body = Expression.Equal(Expression.Property(param, property),
Expression.Property(Expression.Constant(closure), "value"));

另一种方法是实际使用 C# 编译器创建闭包表达式并绑定(bind)它的主体:

Expression<Func<TValue>> closure = () => value;
var body = Expression.Equal(Expression.Property(param, property),
closure.Body);

关于c# - 动态构建 LINQ 查询 - 强制使用 sp_executesql 而不是原始查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51208060/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com