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

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

public static IQueryable GetByIntTest(this IQueryable qSource, Expression<Func> 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>(binaryExpression, field.Parameters); return qSource.Where(predicate); } 

它的工作原理,但问题是它转换为非参数化的sql。

例如没有扩展名的代码

 int userId = 3; var testUsual = Context.Set().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().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这样的东西呢?

更新

感谢我们的回答,我重写了我的扩展方法,现在它生成@p_ linq _0,因为我想要。

 public static IQueryable GetByIntTest(this IQueryable qSource, Expression<Func> field, int? value) { if (value == null) return qSource; var binaryExpression = Expression.Equal(field.Body, ExpressionClosureFactory.GetField(value)); var predicate = Expression.Lambda<Func>(binaryExpression, field.Parameters); return qSource.Where(predicate); } public class ExpressionClosureFactory { public static MemberExpression GetField(TValue value) { var closure = new ExpressionClosureField { ValueProperty = value }; return Expression.Field(Expression.Constant(closure), "ValueProperty"); } class ExpressionClosureField { 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注入为常量表达式。