无法在Linq查询where子句中使用Contains

时间:2014-04-11 18:15:05

标签: c# linq entity-framework

        List<Guid> toBeFilteredCarIds = new List<Guid>();
        toBeFilteredCarIds.Add(new Guid("4cc70c3a-405c-4a5c-b2cd-0429a5bc06ef"));

        var cars = ef.Cars
            .Include("CarProfile.Option.OptionType")
            .Where(c => c.CarStatusId == 1);

        cars.Join(ef.CarProfile,
            t1 => t1.CarId,
            t2 => t2.Car.CarId,
            (t1, t2) => new { t1, t2 }).Where(o => o.t2.IsActive == true).Select(o => o.t1);

        var filteredCars = cars.ToList().Where(u => toBeFilteredCarIds.Contains(u.CarId));

上面的代码试图获取Car的列表,其中CarProfile处于活动状态,CarId位于toBeFilteredCarIds列表中。

然而,正如您在最后一行中所看到的,我首先执行.ToList(),然后使用Where子句来过滤CarIds。

这显然会让所有汽车首先来自DB,然后进行过滤。这是非常昂贵的。

我尝试过别人对其他答案的建议:

        List<Guid> toBeFilteredCarIds = new List<Guid>();
        toBeFilteredCarIds.Add(new Guid("4cc70c3a-405c-4a5c-b2cd-0429a5bc06ef"));

        var cars = ef.Cars
            .Include("CarProfile.Option.OptionType")
            .Where(c => toBeFilteredCarIds.Contains(c.CarId) && c.CarStatusId == 1);

        cars.Join(ef.CarProfile,
            t1 => t1.CarId,
            t2 => t2.Car.CarId,
            (t1, t2) => new { t1, t2 }).Where(o => o.t2.IsActive == true).Select(o => o.t1);

        var filteredCars = cars.ToList();

但这不适合我,它给了我这个错误:

LINQ to Entities无法识别方法'Boolean Contains(System.Guid)'方法,并且此方法无法转换为商店表达式。

我可以在stackoverflow上看到,很多都标记为回答上述方法:

.Where(c => toBeFilteredCarIds.Contains(c.CarId)

但它不适合我。

他们使用的方式是:VS2008,EF 3.5,我在使用语句中使用System.Data.Entity;

上面使用的

“Include”非常重要,因为我需要事先得到所有内容,因为会有大量的循环读取数据后的数据。

3 个答案:

答案 0 :(得分:3)

Contains上的{p> IEnumerable未添加到4.0,因此如果您遇到3.5,则需要执行类似于在发送查询之前展开值的操作。

请注意:http://blogs.msdn.com/b/alexj/archive/2009/03/26/tip-8-writing-where-in-style-queries-using-linq-to-entities.aspx

答案 1 :(得分:0)

由于.NET 3.5不支持Contains,因此您可以使用Dynamic Linq Library,它允许您使用字符串生成where子句。这样,您就不必使用所有Expression语言。

可在NuGet上使用:https://www.nuget.org/packages/System.Linq.Dynamic.Library/

你的Where子句看起来像这样:

.Where("CarStatusId=1 AND (CarId=1 OR CarId=2 OR CarId=3"))

您只需根据toBeFilteredCarIds列表生成该字符串。

答案 2 :(得分:0)

您可以使用Any()。不像Contains()那么优雅,但它在.NET 3.5中完成了工作:

.Where(c => toBeFilteredCarIds.Any(g => g == c.CarId) && c.CarStatusId == 1);