实体框架 - “全部”方法

entity-framework linq linq-to-entities

All方法应该针对列表中的所有元素计算参数。它在常规Linq中运行正常,但是当我尝试将它与EF一起使用时,它会抛出一个错误(“ 无法创建类型为'闭包类型'的常量值。此处仅支持基本类型(例如Int32,String和Guid)上下文。 “)

例:

var myList = from person in entities.People
             where searchList.All(arg => arg == arg).ToList();

(arg == arg这里只是为了说明我的问题)

在我的场景中,searchList是包含搜索项的列表,例如“John”,“Accounting”,“75”。在我的EF查询中,我想检索人员中的所有记录,其中John,Accounting和75出现在某些指定的可搜索字段中。一个更现实的例子是这样的:

where SearchList.All((person.FirstName + " " + person.LastName + " " + person.DepartmentName + " " + person.Phone).Contains)

第二个例子在内存中也适用于Linq,但EF不喜欢它。

请帮忙!我能做些什么才能让它发挥作用?

这是一个来自我的另一个问题的更具体的问题。

示例代码:

IEnumerable<string> searchList = ParseSearchText(searchText); //search text is broken into search tokens - each token is an element in searchList. For instance "John", "Sales", "654"

var peopleQuery = from person in entities.vSearchPeople
where upperSearchList.All((person.FirstName + " " + person.Lastname + " " + person.Phone).ToUpperInvariant().Contains)
select person;

一般承认的答案

实体框架不支持所有查询。如果您想到以下内容,这一点就变得很明显了

dataContext.Persons.Where(person => MyMethod(person));

使用MyMethod()返回一个布尔值。该方法可能会执行所有操作,您无法将所有内容转换为SQL。解决方案是使用ToList()将所有实体放入本地内存,然后使用LINQ to Object。

dataContext.Persons.ToList().Where(person => MyMethod(person));

它取决于您的实际查询是否可以重写,以便它可以由实体框架转换为SQL,或者如果您必须使用LINQ to Object在本地内存中进行查询。

您提到的例外情况听起来像是在尝试以下内容。

Company company = datacontext.Companies.Where(company.Name == "ACME").Single();

dataContext.Employees.Where(employee => employee.Company == company);

LINQ to Entity不支持包含实体的表达式,因此Company实体的比较无效。在这种情况下,您可以按如下方式重写它。

dataContext.Employees.Where(employee => employee.Company.Id == company.Id);

这只比较了id - 一个像整数或GUID这样的基本类型 - 这可以转换为SQL。

逐字搜索示例(另请参阅注释)

IQueryable<People> result = entities.People;

foreach (String item in searchList)
{
    // This copy is important in order not to modify the closure.
    String itemCopy = item;

    result = result.Where(p =>
        p.FirstName.ToUpper().Contains(itemCopy) ||
        p.LastName.ToUpper().Contains(itemCopy) ||
        p.Phone.ToUpper().Contains(itemCopy));
}

这将逐字构造查询。注意到实体框架识别ToUpper()ToLower()Contains() (以及更多) - 所以当我说实体框架不识别方法调用时,我是严格的。它确实,但不是很多,而不是ToUpperInvariant()ToLowerInvariant() 。此外,此查询使用列的排序规则转换为CHARINDEX()函数调用,因此在没有显式ToUpper()ToLower()调用的情况下,搜索可以不区分大小写。


热门答案

这个好例子在All()方法中有什么好处。

model.ReferenceList = db.JournalCardReference.OrderBy(a => a.orderF)
 .Include(x => x.JournalCardField)
  .Where(x => x.JournalCardField
    .All(f => f.deleted == null || f.deleted != true)).ToList();



许可下: CC-BY-SA with attribution
不隶属于 Stack Overflow
这个KB合法吗? 是的,了解原因
许可下: CC-BY-SA with attribution
不隶属于 Stack Overflow
这个KB合法吗? 是的,了解原因