简体   繁体   English

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

[英]EF Core 5 check if all ids from filter exists in related entities

I have two models:我有两个模型:

public class Employee
{
    public int Id { get; set; }
    public IList<Skill> { get; set; }
}

public class Skill
{
    public int Id { get; set; }
}

And I have filter with list of skill ids, that employee should contain:我有技能 ID 列表过滤器,该员工应包含:

public class Filter
{
    public IList<int> SkillIds { get; set; }
}

I want to write query to get all employees, that have all skills from filter.我想编写查询来获取所有具有过滤器所有技能的员工。

I tried:我试过:

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

And:和:

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

But as a result I get exception says that query could not be translated.但结果我得到异常说查询无法翻译。

It is going to be a difficult, if not impossible task, to run a query like this on the sql server side.在 sql server 端运行这样的查询将是一项困难的任务,即使不是不可能的任务。 This is because to make this work on the SQL side, you would be grouping each set of employee skills into a single row which would need to have a new column for every skill listed in the skills table.这是因为要在 SQL 端进行这项工作,您需要将每组员工技能分组到一行中,这需要为skills表中列出的每项技能创建一个新列。 SQL server wasn't really made to handle grouping with an unknown set of columns passed into a query. SQL Server 并不是真正用来处理传递给查询的一组未知列的分组。 Although this kind of query is technically possible, it's probably not very easy to do through a model binding framework like ef core.虽然这种查询在技术上是可行的,但通过像 ef core 这样的模型绑定框架可能不是很容易做到。

It would be easier to do this on the .net side using something like:使用以下内容在 .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()

This solution works:此解决方案有效:

foreach (int skillId in filter.SkillIds)
{
    query = query.Where(e => e.Skills.Any(skill => skill.Id == skillId));
}

I am not sure about it's perfomance, but works pretty fast with small amount of data.我不确定它的性能,但在少量数据的情况下工作得非常快。

For the sake of reference for people who end up here, I've encountered this issue several times now, this is the query I've come up with that I found works best.为了给最终来到这里的人提供参考,我现在已经多次遇到这个问题,这是我提出的我发现效果最好的查询。 Using OP's example:使用OP的例子:

query.Where(e => e.Skills.Where(s => filter.SkillIds.Contains(s.Id)).Count() == filter.SkillIds.Count);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM