在 FromSQL 查询和Where In 子句中使用整数参数数组

Mig*_*ura 8 linq-to-entities entity-framework-core entity-framework-core-3.1

我有一个整数列表:

var ids = 新列表 { 10, 20 };

我需要找到具有该 id 的用户:

context.Users.FromSqlInterpolated($@" 
  select Users.* 
  where Users.Id in ({String.Join(',', ids)})"
Run Code Online (Sandbox Code Playgroud)

但我收到以下错误:

'Conversion failed when converting the nvarchar value '10, 20' to data type int.'
Run Code Online (Sandbox Code Playgroud)

我该如何使用这样的参数?

Iva*_*oev 14

这里使用Interpolatedmethod 是不合适的,因为{String.Join(',', ids)}定义了单个字符串占位符,因此 EF Core 将单个nvarchar参数与 value绑定'10,20',所以实际的 SQL 是这样的

select Users.* 
where Users.Id in ('10,20')
Run Code Online (Sandbox Code Playgroud)

这是无效的,因此是例外。

你应该使用Raw方法来代替。任何一个

var query = context.Users.FromSqlRaw($@" 
select Users.* 
where Users.Id in ({String.Join(',', ids)})");
Run Code Online (Sandbox Code Playgroud)

这将嵌入文字值

select Users.* 
where Users.Id in (10,20)
Run Code Online (Sandbox Code Playgroud)

或者如果你想参数化它,在 SQL 中生成参数占位符{0},如 等,并单独传递值:{1}

var placeholders = string.Join(",", Enumerable.Range(0, ids.Count)
    .Select(i => "{" + i + "}"));
var values = ids.Cast<object>().ToArray();

var query = context.Users.FromSqlRaw($@" 
select Users.* 
where Users.Id in ({placeholders})", values);
Run Code Online (Sandbox Code Playgroud)

这会生成这样的 SQL

select Users.* 
where Users.Id in (@p0,@p1)
Run Code Online (Sandbox Code Playgroud)

  • @kolobcreek 输入只是一个整数列表。祝你的 SQL 注入好运。 (2认同)

Sco*_*NET 5

如果需要组合.FromSql()SQL,则对调用的输出WHERE x IN ()执行第二个操作。IQueryable<T>.FromSql()

var ids = new List { 10, 20 };
var query = context.Users.FromSqlInterpolated(
  $@"select *
     from Users");
if (ids?.Count > 0)
{
  query = query.Where(user => ids.Contains(user.Id));
}
Run Code Online (Sandbox Code Playgroud)

结果 SQL 近似为:

select * from (
  select * 
  from Users
) u
where u.Id in (10,20)
Run Code Online (Sandbox Code Playgroud)
  • 如果 ids 为空则没有无效 SQL
  • 如果 ids 为空字符串,则没有空结果(我正在使用字符串数据类型)