gpt4 book ai didi

c# - 在运行时创建动态 LINQ 查询表达式,转换为参数化 SQL 查询

转载 作者:行者123 更新时间:2023-11-30 22:10:08 24 4
gpt4 key购买 nike

我想为 IQueryable 创建自定义表达式。示例扩展方法:

    public static IQueryable<T> GetByIntTest<T>(this IQueryable<T> qSource, Expression<Func<T, int?>> field, int? value) 
{
if (value == null)
return qSource;

ConstantExpression constantExpression = Expression.Constant(value, typeof(int?));
BinaryExpression binaryExpression = Expression.Equal(field.Body, constantExpression);
var predicate = Expression.Lambda<Func<T, bool>>(binaryExpression, field.Parameters);
return qSource.Where(predicate);
}

它可以工作,但问题是它转换为未参数化的 sql。

例如没有扩展名的代码

int userId = 3;
var testUsual = Context.Set<User>().Where(u => u.Id == userId);

翻译成下一条sql

SELECT [Extent1].[Id] AS [Id],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName],
FROM [dbo].[User] AS [Extent1]
WHERE [Extent1].[Id] = @p__linq__0

及扩展方法

int userId = 3;
var testExtension = Context.Set<User>().GetByIntTest(u => u.Id, userId);

翻译成

SELECT [Extent1].[Id] AS [Id],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName],
FROM [dbo].[User] AS [Extent1]
WHERE 3 = [Extent1].[Id]

那么我如何编写表达式来在 sql 中生成类似 @p_linq_0 的东西?

更新

感谢 usr 的回答,我重写了我的扩展方法,现在它生成了我想要的 @p_linq_0

public static IQueryable<T> GetByIntTest<T>(this IQueryable<T> qSource, Expression<Func<T, int?>> field, int? value) 
{
if (value == null)
return qSource;

var binaryExpression = Expression.Equal(field.Body, ExpressionClosureFactory.GetField(value));
var predicate = Expression.Lambda<Func<T, bool>>(binaryExpression, field.Parameters);
return qSource.Where(predicate);
}

public class ExpressionClosureFactory
{
public static MemberExpression GetField<TValue>(TValue value)
{
var closure = new ExpressionClosureField<TValue>
{
ValueProperty = value
};

return Expression.Field(Expression.Constant(closure), "ValueProperty");
}

class ExpressionClosureField<T>
{
public T ValueProperty;
}
}

最佳答案

我遇到过这个问题。您正在生成 u => u.Id == 3 作为表达式,而 C# 编译器将生成:

class CompilerGeneratedClosure { public int UserId; }
var closure = new CompilerGeneratedClosure() { UserId = 3 };
u => u.Id == closure.UserId

像 C# 编译器那样做。创建一个类来保存 ID 或使用元组。将 closure 作为常量表达式注入(inject)。

关于c# - 在运行时创建动态 LINQ 查询表达式,转换为参数化 SQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21073663/

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