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

如何使用FromSqlInterpolated安全实现SQL IN子句?

安全构建带IN子句的EF Core SQL查询(规避SQL注入)

当你用FromSqlRaw直接拼接IN子句的参数时,Sonar检测到SQL注入风险是因为直接字符串拼接了用户可控输入。而FromSqlInterpolated默认无法直接处理集合参数——EF Core会把整个集合当成单个参数传递,导致SQL语法错误或逻辑失效。下面是几种可行的安全实现方式:

方法1:用FromSqlInterpolated生成独立参数(推荐)

为集合中的每个元素创建独立的SQL参数,确保IN子句完全参数化:

var targetIds = new List<int> { 12, 34, 56, 78 };
// 为每个ID生成唯一参数
var parameters = targetIds.Select((id, idx) => new SqlParameter($"@id{idx}", id)).ToList();
// 拼接参数名作为IN子句的占位符
var paramNames = string.Join(", ", parameters.Select(p => p.ParameterName));

// 执行参数化查询
var result = dbContext.YourEntity
    .FromSqlInterpolated($"SELECT * FROM YourEntity WHERE Id IN ({paramNames})")
    .ToList();

这种方式会生成类似IN (@id0, @id1, @id2, @id3)的SQL,每个参数都是独立的,完全避免了注入风险,Sonar也不会触发告警。

方法2:用FromSqlRaw配合参数数组

如果你更习惯用FromSqlRaw,只要不直接拼接参数值,而是用占位符+参数数组,同样是安全的:

var targetIds = new List<int> { 12, 34, 56 };
// 生成对应数量的占位符
var placeholders = string.Join(", ", Enumerable.Range(0, targetIds.Count).Select(i => $"@p{i}"));

var result = dbContext.YourEntity
    .FromSqlRaw($"SELECT * FROM YourEntity WHERE Id IN ({placeholders})", targetIds.ToArray())
    .ToList();

EF Core会自动将数组中的每个元素绑定到对应的占位符上,实现参数化查询。

方法3:优先使用LINQ Contains(最简洁)

如果不需要手写SQL,直接用LINQ的Contains方法是最优解——EF Core会自动将其转换为参数化的IN子句:

var targetIds = new List<int> { 12, 34, 56 };
var result = dbContext.YourEntity.Where(e => targetIds.Contains(e.Id)).ToList();

这种方式无需手动处理参数,代码更简洁,同时完全规避注入风险。

常见误区

不要直接将集合作为单个参数传入IN子句,比如FromSqlInterpolated($"SELECT * FROM YourEntity WHERE Id IN ({targetIds})")——这会导致EF Core把整个集合对象转换成字符串(比如System.Collections.Generic.List1[System.Int32]`),既不符合SQL语法,也达不到预期查询效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 09:55:09