【问题标题】:Only primitive types or enumeration types are supported in this context此上下文仅支持原始类型或枚举类型
【发布时间】:2013-03-04 21:21:22
【问题描述】:

我已经看到了很多关于这个主题的问题,但我无法对任何一个真正解决我所看到的问题的问题进行分类。我有一个活动实体,它跟踪分配给哪个员工以及哪个员工创建并更新了记录。如果我删除 `where a.AssignedEmployee == currentUser' 代码行,我不会得到下面的运行时错误。

无法创建“DataModels.Employee”类型的常量值。仅有的 在此上下文中支持原始类型或枚举类型。

控制器

var query = from a in db.Activities
            where a.AssignedEmployee == currentUser
            where a.IsComplete == false
            orderby a.DueDate
            select a;
return View(query.ToList());

查看

@model IEnumerable<Data.DataModels.Activity>
..........

【问题讨论】:

  • == 是否执行此方案不支持的引用相等?注意:询问是否不支持 ref 相等性
  • @JaredPar 你说得对……今天的白痴奖给了我。我在周日尝试了 18 种不同的方法来编写此查询,但由于某种原因,在该对象上使用 ID 属性并不是其中之一。我会把它归咎于今天没有星巴克。
  • 咖啡是你的朋友 ;)

标签: c# asp.net-mvc linq entity-framework


【解决方案1】:

我的猜测是该错误表明 EF 无法将 Employee 的相等运算符转换为 SQL(无论您是假设引用相等还是覆盖 == 运算符)。假设Employee 类有一个唯一标识符试试:

var query = from a in db.Activities
            where a.AssignedEmployeeId == currentUser.Id
            where a.IsComplete == false
            orderby a.DueDate
            select a;
return View(query.ToList());

【讨论】:

  • 那太糟糕了...如果 NHibernate 中有一个 Id 工作正常...我知道添加 .Id 并没有那么糟糕,但没有 .Id 更优雅...
【解决方案2】:

它不喜欢您尝试将整个对象相等性转换为数据库查询的事实。您只能使用常量值执行实体框架查询,就像您执行 SQL 查询一样。解决这个问题的方法是比较 ID 以查看 AssignedEmployee 的 ID 是否与员工表中当前用户的 ID 相同。

附带说明,如果您正在跟踪的 currentUser 对象不是 Employee 类型,您可能需要考虑缓存该用户的相应 Employee 记录,以便在以后的查询中更好地引用它。这比试图不断地通过那张桌子要好得多。 (同样,这只会影响你,如果它实际上是在不同的表中)

【讨论】:

    【解决方案3】:

    使用 == 和 obj.Equals 的问题在于实体框架不知道如何将该方法调用转换为 SQL ——即使您将这两个方法重载为可以转换为 SQL 的方法。在 Entity Framework 中解决这个缺点的方法是创建一个方法,该方法返回一个表达式树,它会执行您想要执行的更复杂的相等性检查。

    例如,假设我们有以下类

    public class Person {
        public string Firstname { get; set; } 
        public string Lastname  { get; set; }
    }
    

    为了返回一个Entity Framework可以理解的自定义相等操作,在Person类中添加如下方法:

    public static Expression<Func<Person, bool>> EqualsExpressionTree(  Person rhs )
    {
        return ( lhs ) => string.Equals( lhs.Firstname, rhs.Firstname ) &&
                          string.Equals( lhs.Lastname, rhs.Lastname );
    }
    

    在您的 LINQ 查询中,您可以像这样利用您的自定义相等代码:

    Person anotherPerson = new Person { Firstname = "John", Lastname = "Doe" }
    personCont.Where( Person.EqualsExpressionTree(anotherPerson) );
    //...
    if ( personCont.Any( Person.EqualsExpressionTree(anotherPerson)) ) {
    //...
    

    此外,可以重写 EqualsExpressionTree 方法以调用静态 Equals 方法,从而允许您利用自定义相等逻辑。但是,无论如何,请记住您的代码必须转换为 SQL 表达式,因为毕竟我们是在调用数据库而不是从内存中访问内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多