实体框架:无法创建类型为'System.Collections.Generic.IList`1'的常量值

Sac*_*nth 9 c# lambda linq-to-entities entity-framework-4

这使我今天无法解决问题.我有这个简单的查询

var result =
    DataContext.Accommodations.Where(a => 
        (criteria.MinPrice == null || a.AccommodationRates.Any(r => r.From >= criteria.MinPrice)) &&
        (criteria.MaxPrice == null || a.AccommodationRates.Any(r => r.To <= criteria.MaxPrice)) &&
        (criteria.Locations == null || criteria.Locations.Count == 0 || a.AccommodationPlaceJoins.Any(j => criteria.Locations.Contains(j.Place.PlaceName)))
);
Run Code Online (Sandbox Code Playgroud)

此查询的最后一行导致我出现问题

(criteria.Locations == null ||
 criteria.Locations.Count == 0 ||
 a.AccommodationPlaceJoins.Any(j => criteria.Locations.Contains(j.Place.PlaceName)))
Run Code Online (Sandbox Code Playgroud)

它给出的错误是

无法创建类型为'System.Collections.Generic.IList`1'的常量值.在此上下文中仅支持原始类型(例如Int32,String和Guid').

我甚至没有尝试创建列表.我在这里尝试做的就是带回与一个地方相关的住宿(Place表中通过AccommodationPlaceJoin表链接到住宿表的地名)等于标准中的任何一个地名.Locations(属于IList类型).

我已经尝试将此行更改为此,但它不起作用.

(criteria.Locations == null ||
 criteria.Locations.Count == 0 ||
 a.AccommodationPlaceJoins.Any(j => criteria.Locations.Any(l => l == j.Place.PlaceName)))
Run Code Online (Sandbox Code Playgroud)

Sla*_*uma 37

EF不能创建的常数值null用于比较criteria.Locations == null.您需要将查询拆分为两种情况,并检查查询外的空列表,例如:

var result = DataContext.Accommodations.Where(a => 
    (criteria.MinPrice == null || 
        a.AccommodationRates.Any(r => r.From >= criteria.MinPrice)) &&
    (criteria.MaxPrice == null ||
        a.AccommodationRates.Any(r => r.To <= criteria.MaxPrice)));

if (criteria.Locations != null && criteria.Locations.Count > 0)
{
    result = result.Where(a => a.AccommodationPlaceJoins
        .Any(j => criteria.Locations.Contains(j.Place.PlaceName)));
}
Run Code Online (Sandbox Code Playgroud)

编辑

顺便说一下:在我看来,编写整个查询会使其更易读,并简化必须发送到数据库的SQL:

IQueryable<Accommodation> result = DataContext.Accommodations;

if (criteria.MinPrice != null)
    result = result.Where(a => a.AccommodationRates
        .Any(r => r.From >= criteria.MinPrice));

if (criteria.MaxPrice != null)
    result = result.Where(a => a.AccommodationRates
        .Any(r => r.To <= criteria.MaxPrice));

if (criteria.Locations != null && criteria.Locations.Count > 0)
    result = result.Where(a => a.AccommodationPlaceJoins
        .Any(j => criteria.Locations.Contains(j.Place.PlaceName)));
Run Code Online (Sandbox Code Playgroud)

  • @SachinKainth:发生异常是因为在LINQ to Entities中,查询中的每个表达式和表达式片段都必须可以转换为SQL.比较`criteria.Locations == null`不会在客户端(= .NET)端执行,而是EF也希望将其转换为SQL,然后数据库应该执行比较.但是数据库不知道如何比较.NET/CLR对象引用,它只能检查字符串,int等原始类型的"NULL".无法转换为SQL或支持 - >异常. (3认同)