执行Linq查询会引发异常



我有一个方法,在该方法中,我过滤一个表,并返回与文件管理器匹配的行。方法如下:

public List<RealEstate> GetMatchingRealestatesQuery(RealestateFilter f, RealestateSiteDbContext context)
    {
        IQueryable<RealEstate> realestates = context.RealEstates.Where(x => x.Status == RealEstateStatus.Open);
        realestates = realestates.Where(x => f.Cities.Any( y => x.ZipCode.City.Id == y.Id));
        if (f.MaxRent > 0)
            realestates = realestates.Where(x => x.Rent <= f.MaxRent);
        if (f.MinArea > 0)
            realestates = realestates.Where(x => x.Area >= f.MinArea);
        if (f.MinRooms > 0)
            realestates = realestates.Where(x => x.Rooms <= f.MinRooms);
        realestates = realestates.Where(x => f.RealestateTypes.Has(x.Type));
        realestates = realestates.Where(x => f.RentalPeriod.Has(x.RentalPeriod));
        return realestates.ToList();
    }

然而,每当我调用该方法时,我都会得到以下异常:

无法创建类型为"RealestateSiteModel.City"的常数值。此中仅支持基元类型或枚举类型上下文

我只是简单地构建一个IQueryable,然后通过调用.ToList来执行查询。这个异常的原因是什么?

这里的问题是LINQ不知道如何将复杂的对象/类转换为SQL代码。

通常,如果您要尝试过滤掉调用并将其与内存中的对象进行比较,则需要确保LINQ知道如何处理这些调用(例如,仅使用基元类型的集合):

public List<RealEstate> GetMatchingRealestatesQuery(RealestateFilter f, RealestateSiteDbContext context)
{
    // This works just fine as status is going to be a boolean
    var realestates = context.RealEstates.Where(x => x.Status == RealEstateStatus.Open);
    // Here's where things get tricky as LINQ doesn't know what City is
    // Is there some ID that you could use that might make this easier, 
    // such as x.ZipCode.City.CityId or something?
    realestates = realestates.Where(x => f.Cities.Any( y => x.ZipCode.City == y));
    // Other code omitted for brevity
    return realestates.ToList();
}

如果这不可能,那么通常这类查询很少利用延迟执行,并且通常需要将整个集合存储在内存中,然后通过ToList()调用在内存中进行过滤:

 public List<RealEstate> GetMatchingRealestatesQuery(RealestateFilter f, RealestateSiteDbContext context)
{
    // This will wipe out any deferred execution and perform the
    // rest of your operations in-memory
    var realestates = context.RealEstates.Where(x => x.Status == RealEstateStatus.Open).ToList();
    // Other code omitted for brevity
    return realestates;
}

同样,这种方法并不理想,因为你提取的数据远远超过了你的需要,但为了避免这种情况,你只需要准确地重组你正在查询的内容,并确保LINQ知道如何翻译它。

更新(实际修复)

该问题的实际解决方案涉及删除在以下行的lamdba调用中使用的实体的实际集合:

realestates = realestates.Where(x => f.Cities.Any( y => x.ZipCode.City.Id == y.Id));

由于LINQ不知道如何转换Cities集合的属性并对其进行求值,所以这会失败。但是,您可以将要查询的对象集合存储在内存中,作为基元类型,然后您应该能够使用:

var cities = f.Cities.Select(c => c.ZipCode.City.Id).ToArray();
realestates = realestates.Where(x => cities.Any(c => c == x.Id);

相关内容

  • 没有找到相关文章

最新更新