EF Core 3.x-具有Include的简单LINQ无法翻译,客户端评估

时间:2020-07-05 17:13:27

标签: c# entity-framework linq ef-core-3.1

我有一个简单的LINQ表达式:

public List<Project> GetCheckedProjects(List<PickedUp> displayCollection)
        {
            IQueryable<Project> query = _context.Projects
                .OrderBy(project => project.CompletionDate)
                .Where(project => displayCollection.Any(item => item.ProjectID == project.ProjectID))
                .Include(project => project.TechnologiesProjects)
                .ThenInclude(techproj => techproj.Technology);
            return query.ToList();
        }

这使我失去了运行时异常:

'LINQ表达式'DbSet .OrderBy(p => p.CompletionDate) 哪里(p => __displayCollection_0 .Any(item => item.ProjectID == p.ProjectID))'无法翻译。以可以翻译的形式重写查询, 或通过插入来明确切换到客户评估 AsEnumerable(),AsAsyncEnumerable(),ToList()或 ToListAsync()。有关详情,请参见https://go.microsoft.com/fwlink/?linkid=2101038 更多信息。

this MSDN article中提到,在 EF Core 3.x 中存在重大更改,并且阻止了客户评估。还有

在这种情况下,您可以通过以下方式明确选择接受客户评估 调用诸如AsEnumerable或ToList(AsAsyncEnumerable或 ToListAsync异步)。通过使用AsEnumerable,您将流式传输 结果,但使用ToList会通过创建一个 列表,这也会占用更多内存。

在我的情况下,使用AsEnumerable()时出现异常:

IEnumerable不包含“包含”(...)的定义

在表达式like in this SO answe r的末尾使用ToList()也很简单,不会带来任何积极的结果。

EF Core 2.x 中,我的LINQ正常工作。如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

尝试将ID选择到单独的集合中,并使用Contains

    public List<Project> GetCheckedProjects(List<PickedUp> displayCollection)
    {
        var ids = displayCollection.Select(item => item.ProjectID).ToList();
        IQueryable<Project> query = _context.Projects
            .OrderBy(project => project.CompletionDate)
            .Where(project => ids.Contains(project.ProjectID))
            .Include(project => project.TechnologiesProjects)
            .ThenInclude(techproj => techproj.Technology);
        return query.ToList();
    }

或者,由于此代码将被翻译为查询,因此您可以在一行中完成它:

IQueryable<Project> query = _context.Projects
            .OrderBy(project => project.CompletionDate)
            .Where(project => displayCollection.Select(item => item.ProjectID).Contains(project.ProjectID))
            .Include(project => project.TechnologiesProjects)
            .ThenInclude(techproj => techproj.Technology); 

答案 1 :(得分:0)

Ef Core可能会遇到以下问题:

displayCollection.Any(item => item.ProjectID == project.ProjectID)

尝试用这种方式

public List<Project> GetCheckedProjects(List<PickedUp> displayCollection)
    {
        IQueryable<Project> queryAll = _context.Projects
            .OrderBy(project => project.CompletionDate)                
            .Include(project => project.TechnologiesProjects)
            .ThenInclude(techproj => techproj.Technology);
        
        var query = queryAll
              .ToList()
              .Where(project => displayCollection.Any(item => item.ProjectID == project.ProjectID));       
    
        return query;
    }

我认为这应该可行,因为EF核心不会将Where子句转换为sql查询。常规LINQ应该可以在List上做到这一点。

缺点(如果可行)是,当您调用“ .ToList()”时,您将遍历整个数据库表