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

为什么我会得到这个错误:

无法创建“闭包类型”类型的常量值。仅 中支持基元类型(例如 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 方法上,对吧? 有什么建议吗?

95656 次浏览

看起来您正在尝试执行相当于“ WHERE... IN”条件的操作。有关如何使用 LINQtoEntities 执行此类查询的示例,请参阅 如何使用 LINQtoEntity 编写“ WHERE IN”样式查询

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

在过去的6个月里,我一直在与 EF 3.5的局限性作斗争,虽然我不是世界上最聪明的人,但我很确定在这个话题上我有一些有用的东西可以提供。

生成50英里高的“ OR 样式”表达式树所产生的 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、 Government Id 和 Government IdType 表的模式。Andrew Tappert (Person)有两张 ID 卡(Government Id) ,一张来自俄勒冈州(Government IdType) ,一张来自华盛顿州(Government IdType)。

现在从中生成一个 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 将使用“连接”而不是子查询,但效果是相同的。如今,SQL 服务器总是会将子查询优化为隐藏的连接,但不管怎样... ..。

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

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

在哪里 upperSearchList. All (arg = > person. some property. StartsWith (arg))

我已经找到了错误的原因(我正在使用 Framework4.5)。问题是,EF 是一个复杂的类型,在“ Contains”-参数中传递,不能转换成 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 不再有复杂的类型“函数”的工作,但例如与一个简单的类型(长)。这样很好!