15

这给我今天带来了无穷无尽的问题。我有这个简单的查询

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)))
);

这个查询的最后一行给我带来了问题

(criteria.Locations == null ||
 criteria.Locations.Count == 0 ||
 a.AccommodationPlaceJoins.Any(j => criteria.Locations.Contains(j.Place.PlaceName)))

它给出的错误是

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

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

我试过把这条线改成这个,但没有用。

(criteria.Locations == null ||
 criteria.Locations.Count == 0 ||
 a.AccommodationPlaceJoins.Any(j => criteria.Locations.Any(l => l == j.Place.PlaceName)))
4

1 回答 1

46

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)));
}

编辑

顺便说一句:在我看来,编写整个查询会使其更具可读性,并将简化必须发送到数据库的 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)));
于 2012-09-05T15:19:17.637 回答