【问题标题】:EF Core 3 x.Contains() in expression where x is ICollectionEF Core 3 x.Contains() 在 x 是 ICollection 的表达式中
【发布时间】:2020-01-29 02:21:51
【问题描述】:

我有以下数据层设置:

public class Repository : IRepository {

    private readonly MyDbContext _dbContext;

        public List<Meter> Search(Expression<Func<Meter,bool>> criteria)
            IQueryable<Meter> results = _dbContext.Meters;
            return results.Where(criteria).ToList();
        }
    }
}

... from a client class:

IRepository _repository;

public void ClientMethod () {

    ICollection<int> ids = new List<int>() {1, 2, 3);
    var results = _repository.Search(c=> ids.Contains(c.Id)); // This throws exception

}

这会导致异常:

表达式 Where(source: DbSet, predicate: (m) => (未处理的参数:__ids_0).Contains(m.Id))' 不能 翻译。要么以可以翻译的形式重写查询, 或通过插入调用显式切换到客户端评估 AsEnumerable()、AsAsyncEnumerable()、ToList() 或 ToListAsync()

但如果我将集合引用更改为 IEnumerable 或 List,它会起作用:

public void ClientMethod () {

    // This works
    List<int> ids = new List<int>() {1, 2, 3);
    var results = _repository.Search(c=> ids.Contains(c.Id)); 

    // This works
    IEnumerable<int> ids = new List<int>() {1, 2, 3);
    var results = _repository.Search(c=> ids.Contains(c.Id)); 
}

为什么它不适用于 ICollection,但它适用于 IEnumerable 和 List?我的许多客户端方法都将 ICollection 作为参数。

我使用的是 EF Core 3.0,但我相信我在 2.1 中遇到了同样的问题,只是没有抛出,而是在客户端上评估它。

【问题讨论】:

    标签: c# entity-framework-core ef-core-2.1 ef-core-3.0


    【解决方案1】:

    这是 3.1 中修复的已知错误。由于查询管道重写后的所有回归,3.0 几乎无法使用。

    我建议在 github 上关注 ef core 的问题跟踪器。

    【讨论】:

    【解决方案2】:

    从 2.2 迁移到 EF Core 3.0 时,我遇到了同样的问题。我之前配置过 ef 以在客户端评估时抛出错误,并且它工作正常。所以我确信这是 3.0 的一个新问题,是在他们重写 linq 引擎时引入的。

    将其转换为 IEnumerable 或 List 也适用于我,感谢您的提示!

    【讨论】:

    【解决方案3】:

    当您转换为 IEnumerable() 或 List() 时,EFCore 会强制客户端评估,这就是它起作用的原因。 (但会以性能为代价)

    • “在 3.0 版之前,Entity Framework Core 支持查询中任何位置的客户端评估”Reference
    • 3.0 之前的 EFCore 版本还允许您在混合服务器和客户端评估时添加警告。
    • 然后 EF 更改了策略,不允许您混合服务器和客户端评估,因此不会发生意外的性能问题。不过比这要复杂一些,所以这里有一个指向 EFCore 3.1 breaking changes 的链接 *所有其他版本也可以在这里找到,也可以在左侧菜单导航中找到,包括 3.0。

    【讨论】:

    • 嗯,不再相关了。 EF2 很快就会被遗忘,并且一年多前在 EF3 中修复了错误(或添加的功能,如果您愿意的话)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-17
    • 2021-10-22
    • 2020-04-21
    • 2020-09-10
    • 1970-01-01
    • 1970-01-01
    • 2021-04-13
    相关资源
    最近更新 更多