我在尝试修改SQL查询以解决有关潜在SQL注入的警告时遇到了一个问题。我打算对查询进行参数化并使用原始字符串文字,但我收到了一条错误消息。
这个错误似乎与我的列名的大小写敏感性有关,不幸的是,我不能改变整个数据库来删除它们。
我已经尝试了各种其他方法,但它们要么导致错误,要么无法正确检索UserId。
下面是我试过的代码。
1.原始版本(SQL注入问题)
await dbContext.Database.ExecuteSqlRawAsync(
$@"
DO $$
BEGIN
IF (SELECT COUNT(*) FROM ""Notification"" WHERE ""UserId"" = '{userId}') > 20 THEN
DELETE FROM ""Notification""
WHERE ""UserId"" = '{userId}' AND ""IsReceived"" = 'TRUE' AND ""ContentId"" NOT IN (
SELECT ""ContentId"" FROM ""Notification""
WHERE ""UserId"" = '{userId}'
ORDER BY ""CreatedAt"" DESC
LIMIT 20
);
END IF;
END $$"
);
字符串
1.原始字符串文字版本
(错误:Npgsql.PostgresException:42703:列“userid”不存在)
var param = new NpgsqlParameter("@UserId", userId);
await dbContext.Database.ExecuteSqlRawAsync(
"""
DO $$
BEGIN
IF (SELECT COUNT(*) FROM "Notification" WHERE "UserId" = @UserId) > 20 THEN
DELETE FROM "Notification"
WHERE "UserId" = @UserId AND "IsReceived" = 'TRUE' AND "ContentId" NOT IN (
SELECT "ContentId" FROM "Notification"
WHERE "UserId" = @UserId
ORDER BY "CreatedAt" DESC
LIMIT 20
);
END IF;
END $$
""", param);
型
1.带有ExecuteSqlInterpolatedAsync的原始字符串文本版本
(错误:Npgsql.PostgresException:42703:列“p0”不存在)
await dbContext.Database.ExecuteSqlInterpolatedAsync(
$"""
DO $$
BEGIN
IF (SELECT COUNT(*) FROM "Notification" WHERE "UserId" = {userId}) > 20 THEN
DELETE FROM "Notification"
WHERE "UserId" = {userId} AND "IsReceived" = 'TRUE' AND "ContentId" NOT IN (
SELECT "ContentId" FROM "Notification"
WHERE "UserId" = {userId}
ORDER BY "CreatedAt" DESC
LIMIT 20
);
END IF;
END $$
""");
型
我希望你能告诉我如何进行修改。
感谢您的帮助!
2条答案
按热度按时间iaqfqrcu1#
IF
实际上不是必需的,所以你可以使用一个普通的SqlInterpolated
块(即完全参数化)。字符串
s8vozzvw2#
AFAIK你不能使用
DO
的参数。从docs:DO
执行匿名代码块,或者换句话说,在过程语言中执行临时匿名函数。代码块被视为没有参数的函数体,返回void。它被解析并执行一次。
因此它将参数名视为列名(显然失败了)。
因此,只需重写查询,这样就不需要
DO
,或者创建一个数据库函数并使用EF调用它。参见this answer。