实体框架 - “无法创建类型'闭包类型'的常量值...”错误

时间:2009-05-18 19:40:41

标签: linq entity-framework

为什么我会收到错误:

  

无法创建“闭包类型”类型的常量值。只要   支持原始类型(例如Int32,String和Guid)   这个背景。

当我尝试枚举以下Linq查询时?

IEnumerable<string> searchList = GetSearchList();
using (HREntities entities = new HREntities())
{
   var myList = from person in entities.vSearchPeople
   where upperSearchList.All( (person.FirstName + person.LastName) .Contains).ToList();
}

更新: 如果我尝试以下尝试来隔离问题,我会得到同样的错误:

where upperSearchList.All(arg => arg == arg) 

所以看起来问题出在All方法上,对吧?有什么建议吗?

4 个答案:

答案 0 :(得分:68)

看起来你正试图做相当于“WHERE ... IN”的条件。查看How to write 'WHERE IN' style queries using LINQ to Entities以获取如何使用LINQ to Entities进行该类型查询的示例。

此外,我认为错误消息在这种情况下特别无用,因为.Contains后面没有括号,这会导致编译器将整个谓词识别为lambda表达式。

答案 1 :(得分:11)

我花了最近6个月的时间与EF 3.5争夺这个限制,虽然我不是世界上最聪明的人,但我很确定我在这个主题上有一些有用的东西。

通过增加50英里高的“OR style”表达式树生成的SQL将导致查询执行计划不佳。我正在处理几百万行,影响很大。

我发现有一个小小的黑客攻击,如果你只是通过id寻找一堆实体,那么这有点帮助:

private IEnumerable<Entity1> getByIds(IEnumerable<int> ids)
{
    string idList = string.Join(",", ids.ToList().ConvertAll<string>(id => id.ToString()).ToArray());
    return dbContext.Entity1.Where("it.pkIDColumn IN {" + idList + "}");
}

其中pkIDColumn是Entity1表的主键id列名。

但继续阅读!

这很好,但它要求我已经拥有了我需要找到的东西。有时我只是希望我的表达能够与其他关系联系起来,而我所拥有的是那些相关关系的标准。

如果我有更多的时间,我会尝试直观地表示这一点,但我不会那么只研究这句话:考虑一个包含Person,GovernmentId和GovernmentIdType表的模式。 Andrew Tappert(Person)有两张身份证(GovernmentId),一张来自Oregon(GovernmentIdType),另一张来自华盛顿(GovernmentIdType)。

现在从中生成一个edmx。

现在想象你想要找到所有具有特定ID值的人,比如说1234567。

这可以通过单个数据库命中来实现:

dbContext context = new dbContext();
string idValue = "1234567";
Expression<Func<Person,bool>> expr =
    person => person.GovernmentID.Any(gid => gid.gi_value.Contains(idValue));

IEnumerable<Person> people = context.Person.AsQueryable().Where(expr);

你在这里看到子查询吗?生成的sql将使用'join'而不是子查询,但效果是相同的。现在,SQL服务器无论如何都将子查询优化为封面下的连接,但无论如何......

这项工作的关键是表达式中的.Any。

答案 2 :(得分:8)

我找到了错误的原因(我正在使用Framework 4.5)。问题是,EF是一个复杂类型,它在“包含”参数中传递,不能转换为SQL查询。 EF只能在SQL查询中使用简单类型,如int,string ...

this.GetAll().Where(p => !assignedFunctions.Contains(p))

GetAll提供具有复杂类型的对象列表(例如:“Function”)。因此,我会尝试在我的SQL查询中接收这个复杂类型的实例,这自然不起作用!

如果我可以从我的列表中提取适合我搜索的参数,我可以使用:

var idList = assignedFunctions.Select(f => f.FunctionId);
this.GetAll().Where(p => !idList.Contains(p.FunktionId))

现在EF不再具有复杂类型“功能”,但是例如使用简单类型(长)。这很好用!

答案 3 :(得分:0)

当我在.All函数中使用的数组对象为null时,我收到此错误消息 在我初始化数组对象(在你的情况下为upperSearchList)之后,错误就消失了 在这种情况下,错误消息具有误导性

where upperSearchList.All(arg =&gt; person.someproperty.StartsWith(arg)))