在 mysaladmin 或 HeidiSQL 中工作的简单查询如下所示
SELECT a.SiteId FROM Analyses a WHERE a.AnalysisResultData <> '[]'
AnalysisResultData
是mariadb中的一个json列。
我正在使用 EF.core 最新 8x 版本 + 最新 Pomelo 8.x 版本和 尝试通过 LINQ 构建类似的东西(暂时用
a.SiteId
替换 *
):
await _dbContext.Analyses.CountAsync(a => a.AnalysisResultData != new List<AnalysisResultData>());
调试日志记录创建以下查询
26.02.2024 07:38:19.906 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (92ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT COUNT(*)
FROM `Analyses` AS `a`
WHERE `a`.`AnalysisResultData` <> '[]'
当我在 HeidiSQL 中执行生成的查询时,我得到了正确的结果(~2K)。 但是 LINQ 语句虽然是正确的 SQL,但始终返回空结果。
这里的问题是
[]
括号。 AnalysisResultData
是一个 json 列,我似乎无法以某种方式转义这些括号来实际获得结果,因为 EF.core 本身做了一些括号魔术来防止注入或奇怪的列名称等。
我还在 EF.Core 上尝试了一些 RAW Sql,以避免使用 JSON 转换器时遇到的任何问题:
var result = _dbContext.Database.SqlQueryRaw<int>($"SELECT a.SiteId as Value " +
$"FROM Analyses a WHERE a.AnalysisResultData <> '[]'").ToList();
result
,但在 EF.core 中始终为 0。
我试过:
'\[\]'
[[]]
那么,转义括号的正确方法是什么?
在你问:“为什么要用
$
插入所有这些字符串?”
答案:这些查询非常脆弱,为了提高其稳健性,我使用
$"SELECT {nameof(AnalysisResult.SiteId)} as Value ... "
插入名称。 (不要盲目地对用户提供的参数这样做,除非您的要求明确指出您的软件必须容易受到 SQL 注入😅)
对于这里的重现案例来说并不重要。
在写我的问题并整理我迄今为止尝试过的列表时,我开始测试最愚蠢的转义方式。无论出于何种原因,这都是正确的转义:
[][]
(我尝试在EF.core中搜索括号转义逻辑,但没有找到这些细节)
_dbContext.Database.SqlQueryRaw<int>($"SELECT a.SiteId as Value " +
$"FROM Analyses a WHERE a.AnalysisResultData <> '[][]'"
EF.Core 在 EF 之外创建一个查询不可用 作为 SQL:
SELECT a.SiteId as Value FROM Analyses a WHERE a.AnalysisResultData <> '[][]'
在 HeidiSQL 中,这实际上返回我 ALL 条目,而不仅仅是那些具有空
AnalysisResultData
列的条目。 (=糟糕)
但在 EF.core 中,结果集是正确。
这是一个非常晦涩的解决方案,我希望有更好的方法来做到这一点。
在那之前:如果有人需要这个,你真的应该,真的,真的,真的,真的对此进行自动化测试。当您更新 EF.core 或第三方提供商时,这种行为看起来可能随时会中断。