此上下文仅支持原始类型或枚举类型
Posted
技术标签:
【中文标题】此上下文仅支持原始类型或枚举类型【英文标题】: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 属性并不是其中之一。我会把它归咎于今天没有星巴克。
咖啡是你的朋友 ;)
【参考方案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 表达式,因为毕竟我们是在调用数据库而不是从内存中访问内容。
【讨论】:
以上是关于此上下文仅支持原始类型或枚举类型的主要内容,如果未能解决你的问题,请参考以下文章
无法创建类型为“x”的常量值。此上下文仅支持原始类型或枚举类型
实体框架,无法创建类型为“XX”的常量值。此上下文仅支持原始类型或枚举类型
无法创建类型为“EShop.ClassLibrary.ProductType”的常量值。此上下文仅支持原始类型或枚举类型