提高EF查询性能 - 检查预取List <string>中是否存在行

时间:2016-11-05 18:57:43

标签: c# .net entity-framework linq

我有以下(通用)查询:

var listOfPossibleCars= new List<string>();
var listOfCars = db.Cars.Where(s => listOfPossibleCars.Contains(s.CarName)).ToList();

listOfPossibleCars很大,包含数十万条记录。这个查询引起了延迟,我想知道如何改进它。

2 个答案:

答案 0 :(得分:2)

而不是使用内存中的集合执行此操作而不是将listOfPossibleCars的数据插入到具有正确定义的索引和分区的临时表中,并将其发生在数据库中。使用正确定义的表,数据库将执行散列连接。

数据在数据库中之后,查询将如下所示:

//Instead data to database
from car in db.Cars
join possibleCar in db.PossibleCars on car.CarName equals possibleCar.CarName
select car;

答案 1 :(得分:2)

如果listOfPossibleCars是相对静态的(根本不变或至少不经常变化),您可以将其放入数据库中,如另一个答案中所述。如果不是这种情况并假设您使用sql server,则可以使用表值参数。请注意,使用Contains实体框架非常慢,特别是在长列表中。

首先在数据库中创建自定义表类型:

CREATE TYPE MyType AS TABLE 
(
    CarName varchar(200) primary key    
)

然后像这样查询(注意这是我脑子里的代码,没有经过测试,所以问一下是不是很顺利):

var listOfPossibleCars = new List<string>();
var dt = new DataTable();
dt.Columns.Add("CarName");
foreach (var car in listOfPossibleCars) {
     dt.Rows.Add(car);
}
var possibleCars = new SqlParameter("possibleCars", SqlDbType.Structured);
possibleCars.Value = dt;
possibleCars.TypeName = "dbo.MyType";

var listOfCars = db.Cars.SqlQuery("select C.* from Cars C inner join @possibleCars P on C.CarName = P.CarName", possibleCars).ToList();

是的,您必须使用原始SQL查询,但如果您的列表非常庞大 - 您无法单独使用Entity Framework进行此类查询。