我正在尝试将使用EF的.FromSqlRaw()方法运行的sql查询转换为使用.FromSqlInterpolated()运行的查询,这样它们就不会那么容易受到SQL注入攻击。我几乎把所有的东西都转换了,工作得很好,但唯一让我头疼的是如何在单个字段上通过一个或一个配置中的整数列表进行筛选。数据库是postgres,引号是因为我首先使用了代码EF Core,这意味着所有表都像类一样大写。ProjectTypeId是表中的整数列,projectTypes是List<int>
类型变量。
我要替换的where子句中的代码是:
WHERE ""PartGroups"".""ProjectTypeId"" IN({string.Join(",", projectTypes)})
我最近才能让它发挥作用的是:
""PartGroups"".""ProjectTypeId""::text IN({string.Join(",", projectType)})
或
""PartGroups"".""ProjectTypeId""::text LIKE ANY(ARRAY[{string.Join(",", projectTypes)}])
当projectTypes中只有一个值时,这些方法就会起作用,但是如果超过这个值,那么它就会失败。我不知道如何查看结果的查询+参数集,只是查询,所以我不知道它对参数做了什么,所以我一直在努力找出一些有用的东西。另外,查询总共有80个参数,因此手动设置每个参数的原始查询是不可行的。
发布于 2021-12-16 23:38:11
一种可能的方法是利用EF的能力在原始的顶部作曲。
context.SomeTable
.FromSqlInterpolated($"SeLeCt t.* FrOm ...")
.Where(st => idList.Contains(st.id))
EF将把您的SQL作为子查询,并在外部为您编写in。如果可以的话,DB查询优化器(很可能)会将IN推入子查询。
SELECT ...
FROM
(
SeLeCt t.* FrOm ...
) x
WHERE x.ID IN (.., ..)
如果您想查看所生成的SQL,并且您在EF5+上,那么最简单的方法就是做除ToList/ToArray之外的所有事情,并捕获查询:
var q = context.Thing.Where(...)
然后在调试器中暂停并查看q
的q
属性。您将得到完整的SQL文本,您可以将其插入SSMS并检查执行计划,检查它是否运行与单一级别(非分层)查询相同。
发布于 2021-12-17 07:36:02
您可以做的另一件事是自己在FormattableString中创建查询。只要FromSqlInterpolated收到一个FormattableString,它就会拆开它并参数化。
var args = new object[] { your, single, arguments, here}.Concat(yourListOfThingsHere.Cast<object>()).ToArray();
var fs = FormattableStringFactory.Create(@"SELECT
some,
columns/{0},
here
FROM
table t
WHERE
someColumn = {1} AND
otherColumn BETWEEN {2} and {3} AND
columnToBeINned IN({" + string.Join("},{", Enumerable.Range(4, yourListOfThingsHere.Count)) + @"})
GROUP BY some, columns/{0}", args);
var qq = context.Table.FromSqlInterpolated(fs).Where(m => ...);
当然,可以写个帮手来帮你.
发布于 2021-12-17 16:14:08
因此,我找到了一种方法,可以看到EF Core是如何解释内插查询的参数的,并且能够利用它来获得我想要的内容。因此,如果有人想要或需要坚持纯内插查询,您可以根据您的需要使用以下模式:
WHERE MyTable.MyIntColumn::text LIKE ANY(Array[{string.Join(",", myIntList).Split(",", StringSplitOptions.None)}])
这也适用于文本值(只是不需要转换为文本),您可以使用如下通配符:
WHERE MyTable.MyStringColumn ILIKE ANY(ARRAY[{("%" + string.Join("%,%", myStringList) + "%").Split(",", StringSplitOptions.None)}])
https://stackoverflow.com/questions/70386005
复制相似问题