我最近更新了EF Core 6到7,现在查询变得比以前慢了很多,没有任何变化。看起来EF Core将LINQ查询转换为不同的SQL查询。
版本:
- .NET:7个
- EF核心:7.0.3
这是LINQ查询:
UPDATE:这是错误的,列表标签确实包含了null
。这是完全不期望的,因为我们没有打开可空引用类型,所以我们没有更快地捕获它。
int userId = 3;
List<string> labels = new () { "one", "two", "three" };
List<RecordEntity> alreadySyncedEvents = await _dbContext.RecordEntities
.IgnoreQueryFilters()
.Where(x => x.UserId == userId)
.Where(x => labels.Contains(x.Label))
.Include(x => x.ExtraData)
.ToListAsync();
以下是生成的SQL:
SELECT [a].[Id], [a].[Label], [a0].[Id], [a0].[ExtraData]
FROM [RecordEntities] AS [a]
LEFT JOIN [ExtraDataEntities] AS [a0] ON [a].[Id] = [a0].[RecordId]
WHERE ([a].[UserId] = 3) AND ([a].[Label] IN (N'one', N'two', N'three') OR ([a].[Label] IS NULL))
ORDER BY [a].[Id]
问题是OR ([a].[Label] IS NULL)
导致此查询返回超过13k条记录,而在切换到EF Core 7之前,它返回1。它添加的唯一内容是额外的OR
条件。
这是因为我没有使用可为空的引用类型,而这个字符串在默认情况下是可为空的吗?可为空的引用类型在这个项目中是完全禁用的。
3条答案
按热度按时间bwntbbo31#
您可以添加额外条件
这似乎是一个bug,尽管您可能希望检查
UseRelationalNulls(true)
的配置,另请参见https://learn.microsoft.com/en-us/ef/core/querying/null-comparisons#using-relational-null-semantics44u64gxh2#
由于它们更改了EF Core 7中
OR
运算符的行为,因此需要显式检查空值。使用
||
运算符将以下检查添加到第二个Where()
,如下所示:它应该像老EF那样工作。
bihw5rsg3#
我发现问题了。
列表
labels
不应该包含空值,因为它是基于我们从另一个API(Microsoft Graph API)获得的列表,我们不应该期望空值。但由于一个bug,一个空值确实滑入其中。因此EF Core添加了一个OR ([a].[Label] IS NULL)
。如果我显式过滤列表中的空值,查询将不再包含OR ([a].[Label] IS NULL)
。我们开始在另一个分支中启用可空引用类型是一件好事,这样我们就可以更快地发现它。
这仍然是一个奇怪的巧合,这正好发生在我们切换到EF核心7的那一天。