You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让EF Core 6生成带参数化查询的IQueryable<T>

解决EF Core中ApplyFilter扩展方法不生成参数化SQL的问题

问题背景

实现了用于动态构建过滤条件的ApplyFilter扩展方法,但调用时生成的SQL直接将过滤值硬编码(如WHERE [m].[BrandId] = 2618),而非参数化形式,存在SQL注入风险。

问题根源

代码中使用Expression.Constant将过滤值直接嵌入表达式树,EF Core会把这类直接的常量值编译为SQL中的硬编码内容,不会自动参数化。只有当表达式树引用外部局部变量时,EF Core才会将其识别为需要参数化的输入。

修改方案

修改BuildCriteriaExpression方法中创建常量表达式的逻辑,将转换后的值先赋值给局部变量,再通过Expression.Constant引用该变量,让EF Core自动生成参数化SQL。

关键修改点

  1. 单值过滤场景(Equal/NotEqual等操作符)
    原代码:

    var constantValue = Convert.ChangeType(criteriaNode.Value, propertyType);
    constant = Expression.Constant(constantValue);
    

    修改为:

    var constantValue = Convert.ChangeType(criteriaNode.Value, propertyType);
    // 用局部变量存储值,触发EF Core参数化
    var valueHolder = constantValue;
    constant = Expression.Constant(valueHolder, propertyType);
    
  2. Between操作符场景
    原代码:

    var min = Expression.Constant(constantValues[0], propertyType);
    var max = Expression.Constant(constantValues[1], propertyType);
    

    修改为:

    var minValue = constantValues[0];
    var maxValue = constantValues[1];
    var min = Expression.Constant(minValue, propertyType);
    var max = Expression.Constant(maxValue, propertyType);
    
  3. Any操作符场景
    原代码:

    var arrayInitializer = convertedValue.Select(x => Expression.Constant(x, propertyUnderlyingType));
    

    修改为:

    var arrayInitializer = convertedValue.Select(x => {
        var item = x;
        return Expression.Constant(item, propertyUnderlyingType);
    });
    

修改后效果

修改后生成的SQL会变为参数化形式,例如:

SELECT [a].[AssetId], [a].[AssetCode], [a].[SerialNumber], [a].[LocationId], [m].[ModelName], [m].[Description] AS [ModelDescription], [b].[BrandName], [a0].[AssetTypeName], [c].[CategoryName]
FROM [Asset] AS [a]
INNER JOIN [Model] AS [m] ON [a].[ModelId] = [m].[ModelId]
INNER JOIN [Brand] AS [b] ON [m].[BrandId] = [b].[BrandId]
INNER JOIN [AssetType] AS [a0] ON [m].[AssetTypeId] = [a0].[AssetTypeId]
INNER JOIN [Category] AS [c] ON [m].[CategoryId] = [c].[CategoryId]
WHERE [m].[BrandId] = @__valueHolder_0

内容的提问来源于stack exchange,提问作者Abdelrahman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 04:55:55