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

Gus*_*nti 79 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();
}
Run Code Online (Sandbox Code Playgroud)

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

where upperSearchList.All(arg => arg == arg) 
Run Code Online (Sandbox Code Playgroud)

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

Dan*_*att 68

看起来你正试图做相当于"WHERE ... IN"的条件.查看如何使用LINQ to Entities编写'WHERE IN'样式查询,以获取如何使用LINQ to Entities进行该类型查询的示例.

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

  • LINQ to Entities是一项很棒的技术,但SQL转换引擎是有限的.我不能把我的手放在官方文档上,但根据我的经验,如果查询不仅包括基本的数学和字符串/日期函数,它就不会起作用.你有机会看看我链接的帖子吗?它描述了将"WHERE..IN"类型查询转换为LINQ to Entities然后可以转换为SQL的形式的过程. (2认同)

and*_*rew 11

过去6个月我一直在与EF 3.5争夺这个限制,虽然我不是世界上最聪明的人,但我很确定我在这个主题上有一些有用的东西.

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

我发现做一个SQL'in'有点麻烦,如果你只是通过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 + "}");
}
Run Code Online (Sandbox Code Playgroud)

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

但继续阅读!

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

如果我有更多的时间,我会尝试直观地表示这一点,但我不会那么只研究这句话:考虑一个带有Person,GovernmentId和GovernmentIdType表的模式.Andrew Tappert(人)有两张身份证(GovernmentId),一张来自俄勒冈州(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);
Run Code Online (Sandbox Code Playgroud)

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

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


pet*_*r70 8

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

this.GetAll().Where(p => !assignedFunctions.Contains(p))
Run Code Online (Sandbox Code Playgroud)

GetAll提供具有复杂类型的对象列表(例如:"Function").所以,我会在这里尝试在我的SQL查询中接收这个复杂类型的实例,这自然是行不通的!

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

var idList = assignedFunctions.Select(f => f.FunctionId);
this.GetAll().Where(p => !idList.Contains(p.FunktionId))
Run Code Online (Sandbox Code Playgroud)

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