查询 (LINQ) 表达式无法转换为实体框架核心

Posted

技术标签:

【中文标题】查询 (LINQ) 表达式无法转换为实体框架核心【英文标题】:The Query (LINQ) expression could not be Translated Entity Framework Core 【发布时间】:2021-11-15 01:45:50 【问题描述】:

我正在使用 EntityFrameworkCore 3.1.11 并有以下查询

 var list = _context.Table1
                  .Include(i => i.ListofGroupIds)
                  .Where(i => 
                          i.ListofGroupIds.Select(x => x.GroupId).Any(m =>
                          SelectedIds.Where(z => z.CreatedDate <= i.SentDate).Select(y => y.Id).Contains(m)
                       ))
                   );

在这里,我需要检查 SelectedIds(具有 Id、CreatedDate 和其他字段等属性的列表)中存在的任何项目(Id)是否是 ListOfGroupIds 的一部分,据此我需要获取行。但是我得到了运行时异常

,要么以可翻译的形式重写查询,要么通过插入对 AsEnumerable()、AsAsyncEnumerable()、ToList 的调用显式切换到客户端评估() 或 ToListAsync()。请参阅https://go.microsoft.com/fwlink/?linkid=2101038 了解更多信息。

我查看了与此相关的不同帖子,甚至尝试过enter link description here

我只有一个可行的解决方案是将 AsEnumerable 添加到查询中。但我不希望它是 AsEnumerable,因为我正在处理大量数据,并且我无法拆分包含查询,因为我需要检查ANY 中的一个条件(i.SentDate)。

因此,如果有任何方法可以在单个查询中执行此操作而无需 AsEnumerable

【问题讨论】:

“SelectedIds”从何而来? SelectedIds 只是一个具有 Id,CreatedDate 和其他字段等属性的列表 请提供有关该问题的更多详细信息。 “SelectedIds”是“Table1”的一部分吗? 那么,在我看来有点断章取义,这可能是它无法翻译的原因。如果要检索这两个列表的行,为什么不使用连接? 当然,不过请注意我并不了解所有细节 【参考方案1】:

假设这是您拥有的结构(我故意忽略您可能拥有的所有外键,这只是一个示例!)

public class Table1

    public int Id  get; set; 

    public virtual ListofGroupIds ListofGroupIds  get; set; 


public class ListofGroupIds

    public int GroupId  get; set; 
    public DateTime SentDate  get; set; 


public class SelectedIds

    public int Id  get; set; 
    public DateTime CreatedDate  get; set; 


public class MyContext : DbContext

    public DbSet<Table1> Table1  get; set; 
    public DbSet<ListofGroupIds> ListofGroupIds  get; set; 
    public DbSet<SelectedIds> SelectedIds  get; set; 

您可以将查询重写为

var query = from tab1 in _context.Table1
                    join logi in _context.ListofGroupIds on tab1.Id equals logi.GroupId
                    join sids in _context.SelectedIds on logi.GroupId equals sids.Id
                    where sids.CreatedDate <= logi.SentDate
                    select new  tab1.Id, logi.GroupId, sids.CreatedDate ; //You can select any other columns within the tables joined

或者,如果可能,只需连接所需的两个表

var query2 = from logi in _context.ListofGroupIds
                     join sids in _context.SelectedIds on logi.GroupId equals sids.Id
                     where sids.CreatedDate <= logi.SentDate
                     select new  logi.GroupId, logi.SentDate, sids.Id, sids.CreatedDate ;

或者

var query3 = _context
            .ListofGroupIds.Join(_context.SelectedIds, logi => logi.GroupId, sids => sids.Id, (logi, sids) => new  logi.GroupId, logi.SentDate, sids.Id, sids.CreatedDate )
            .Where(result => result.CreatedDate <= result.SentDate);

【讨论】:

感谢您的回答,即使这不是确切的解决方案,但我可以根据我的目的进行修改

以上是关于查询 (LINQ) 表达式无法转换为实体框架核心的主要内容,如果未能解决你的问题,请参考以下文章

实体框架,LINQ 查询

将 sql 转换为 LINQ C#

使用 LINQ 和实体框架在一个 SQL 查询中从多个表中提取数据

在实体框架核心和linq中查询时可以写case吗?

实体框架 - 荒谬的查询,将 smallint 转换为 int 进行比较 [重复]

如何在 LINQ 查询中使用自定义方法