Entity Framework 3.0 Contains 无法像在 EF Core 2.2 中那样在 SQL 中进行转换

Ale*_*xei 10 entity-framework-core .net-core-3.0 entity-framework-core-3.0

我正在尝试将 Web API 从 .NET Core 2.2 迁移到 .NET Core 3.0,但我偶然发现了以下内容:

public Dictionary<int, Tag> GetTagMap(IList<int> tagIds = null)
{
    var tags = context.Tag.AsNoTracking();
    if (tagIds != null)
        tags = tags.Where(t => tagIds.Contains(t.TagId));

    return tags
       .ToList()       // explicit client evaluation in 3.0
       .ToDictionary(t => t.TagId, t => t);
}
Run Code Online (Sandbox Code Playgroud)

这用于生成与此类似的 SQL 语句:

SELECT TagId, Name FROM Tag WHERE TagId IN (1, 2, 3)
Run Code Online (Sandbox Code Playgroud)

这对于正确索引的列和少量IN值非常有效。

现在我收到以下错误提示List<>.Contains不再支持翻译:

System.InvalidOperationException: '无法翻译 LINQ 表达式'Where( source: DbSet, predicate: (t) => (Unhandled parameter: __tagIds_0).Contains(t.TagId))'。以可翻译的形式重写查询,或通过插入对 AsEnumerable()、AsAsyncEnumerable()、ToList() 或 ToListAsync() 的调用显式切换到客户端评估。有关详细信息,请参阅客户端与服务器评估 - EF Core。

这表明LINQ 查询不再在客户端重大更改上进行评估,但 AFAIKContains未在客户端上进行评估。

Iva*_*oev 12

这是一个 3.0 错误,由#17342跟踪:包含在通用 IList/HashSet/ImmutableHashSet 上将抛出异常

已在 3.1 中修复。解决方法(如果您迫不及待的话)是强制使用Enumerable.Contains,例如

t => tagIds.AsEnumerable().Contains(t.TagId)
Run Code Online (Sandbox Code Playgroud)

或者改变变量的类型。

  • 我从 EF Core 5 得到同样的行为 (3认同)
  • 你好,我认为该错误尚未修复 (2认同)