对实体的限制:如何使用非原始类型进行过滤

问题描述 投票:0回答:2

EF不允许在查询中使用非原始类型,因为它们无法转换为SQL。如果尝试,可能会遇到相同的异常:

'无法创建类型的常量值'SomeType'。只有原始的上下文中支持类型或枚举类型。'

我的问题是下面的代码还有什么其他选择:

public class SkillFilter
{
    public IEnumerable<EmployeeSkill> TargetSkills { get; set; }

    public IQueryable<Employee> Filter(IQueryable<Employee> employees)
    {
        return employees.Where(employee =>
            TargetSkills.Any(targetSkill => employee.Skills
                       .Any(empSkill =>
                           empSkill.SkillId == targetSkill.SkillId &&
                           empSkill.Proficiency == targetSkill.Proficiency)));


    }
}

public class EmployeeSkill
{
    public Guid Id { get; set; }
    public Guid EmployeeId { get; set; }
    public Employee Employee { get; set; }
    public Guid SkillId { get; set; }
    public Skill Skill { get; set; }
    public SkillProficiency? Proficiency { get; set; }
}

public enum SkillProficiency
{
    Basic = 1,
    Novice = 2,
    Intermediate = 3,
    Advanced = 4,
    Expert = 5
}

我需要从Skills属性中找到至少具有一种技能的所有员工。而且我不能使用原始类型,因为我不仅需要检查技能的ID,还需要检查其熟练程度。

首先-不使用ToList()是选项。我正在尝试寻找一种在数据库而不是内存中对其进行过滤的方法。

我已经尝试过的选项:

1)通过IEqulityComparer使用Contains方法。出现相同的错误

    ...
return employees.Where(employee =>
                 TargetSkills.Any(targetSkill =>
                    employee.Skills.Contains(targetSkill, new EmployeeSkillComparer())));

...

public class EmployeeSkillComparer : IEqualityComparer<EmployeeSkill>
    {
        public bool Equals(EmployeeSkill x, EmployeeSkill y)
        {
            return x.SkillId == y.SkillId && x.Proficiency == y.Proficiency;
        }

        public int GetHashCode(EmployeeSkill obj)
        {
            return obj.SkillId.GetHashCode();
        }
    }
  1. 使用加入。遇到相同的错误。

...

return from e in employees
               where (from empSkill in e.Skills
                      join targetSkill in TargetSkills
                      on new {empSkill.SkillId, empSkill.Proficiency} equals 
                         new {targetSkill.SkillId, targetSkill.Proficiency}
                      select empSkill).Any()
               select e;

...

编辑

我对更改属性类型[[熟练程度的建议很少。我在上面的示例中得到的异常表示:

'无法创建类型的常量值'DynamicTargeting.Data.Models.Employees。

EmployeeSkill

。只有原始的类型或枚举类型在此上下文中受支持]所以问题不在Profiency中,而是在类[[EmployeeSkill中。熟练程度为[[enum,并将其翻译为

int,没有任何问题。但是为了不仅仅依赖异常消息,我将其类型更改为原始类型-int。错误仍然相同。不过,谢谢你们的答复!

c# entity-framework linq linq-to-sql linq-to-entities
2个回答
0
投票

我认为最简单的方法(可能不是最有效的,但这里是一般思想)是通过对员工的扩展方法来完成的


0
投票
由于它返回布尔值,因此您可以将其包含在.Where子句中。
© www.soinside.com 2019 - 2024. All rights reserved.