EF Core 5检查过滤器中的所有ID是不是存在于相关实体中

Posted

技术标签:

【中文标题】EF Core 5检查过滤器中的所有ID是不是存在于相关实体中【英文标题】:EF Core 5 check if all ids from filter exists in related entitiesEF Core 5检查过滤器中的所有ID是否存在于相关实体中 【发布时间】:2021-12-11 08:51:07 【问题描述】:

我有两个模型:

public class Employee

    public int Id  get; set; 
    public IList<Skill>  get; set; 


public class Skill

    public int Id  get; set; 

我有一个包含技能 ID 列表的过滤器,该员工应包含:

public class Filter

    public IList<int> SkillIds  get; set; 

我想编写查询来获取所有具有过滤器技能的员工。

我试过了:

query.Where(e => filter.SkillIds.All(id => e.Skills.Any(skill => skill.Id == id)));

还有:

query = query.Where(e => e.Skills
                .Select(x => x.Id)
                .Intersect(filter.SkillIds)
                .Count() == filter.SkillIds.Count);

但结果我得到异常说无法翻译查询。

【问题讨论】:

【参考方案1】:

在 sql server 端运行这样的查询将是一项艰巨的任务,如果不是不可能的话。 这是因为要在 SQL 端进行这项工作,您需要将每组员工技能分组到一行中,这需要为skills 表中列出的每个技能都有一个新列。 SQL Server 并没有真正用来处理传递给查询的一组未知列的分组。虽然这种查询在技术上是可行的,但通过 ef core 这样的模型绑定框架可能不太容易做到。

在 .net 端使用类似这样的东西会更容易:

var employees = _context.Employees.Include(x=>x.Skill).ToList();
var filter = someFilter;
var result = employees.Where(emp => filter.All(skillID=> emp.skills.Any(skill=>skill.ID == skillID))).ToList()

【讨论】:

感谢您的回答!我用找到的解决方案添加了答案【参考方案2】:

此解决方案有效:

foreach (int skillId in filter.SkillIds)

    query = query.Where(e => e.Skills.Any(skill => skill.Id == skillId));

我不确定它的性能,但在少量数据的情况下运行速度很快。

【讨论】:

以上是关于EF Core 5检查过滤器中的所有ID是不是存在于相关实体中的主要内容,如果未能解决你的问题,请参考以下文章

EF CORE PostgreSQL - 检查列表的所有元素是不是包含在另一个列表中

EF Core 过滤掉多对多关系中的重复实体

具有字段值的 EF Core 结果存在于数组中

.net ef core 检查是不是插入成功

.net ef core 检查是不是插入成功

EF Core 5.0 中的多对多关系是不是可以配置为仅保留一个导航属性(在一侧)?