【问题标题】:Linq to Entities: how to filter using Non-Primitive typesLinq to Entities:如何使用非原始类型进行过滤
【发布时间】:2020-03-19 19:07:51
【问题描述】:

EF 不允许在查询中使用非原始类型,因为它们不能被翻译成 SQL。 如果你尝试,你可能会得到同样的例外:

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

我的问题是我对下面的代码还有哪些其他选择:

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) 将 Contains 方法与 IEqulityComparer 一起使用。遇到同样的错误

    ...
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'。只有原始 在此上下文中支持类型或枚举类型

所以问题不在于精通,而在于EmployeeSkill类。 Proficiency 是 enum 并且它被翻译成 int 没有任何问题。 但为了不只依赖异常消息,我将其类型更改为原始类型 - int。 错误还是一样。不过还是谢谢大家的回复!

【问题讨论】:

  • 在你的实体类中你需要定义int类型而不是SkillProficiency
  • @MichałTurczyn 感谢您的回复,但这并不能解决问题。我在编辑部分添加了详细的答案。

标签: c# entity-framework linq linq-to-sql linq-to-entities


【解决方案1】:

您应该尝试比较枚举类型的转换值。试试empSkill.Proficiency.ToString() == targetSkill.Proficiency.ToString()

【讨论】:

  • 感谢您的回复,但并没有解决问题。我在编辑部分添加了详细的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-13
  • 2011-06-10
  • 1970-01-01
  • 1970-01-01
  • 2014-05-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多