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

Improving EF Query Performance - checking if rows exist in a prefetched List<string>

我有以下(通用)查询:

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

但是 listOfPossibleCars 很大,任何包含数十万条记录。此查询导致延迟,我想知道如何改进它。

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

数据存入数据库后,查询将如下所示:

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

如果 listOfPossibleCars 相对静态(根本不改变或至少不经常改变),您确实可以按照另一个答案中的描述将其放入数据库。如果不是这种情况并假设您使用 sql 服务器,则可以使用 table 值参数。请注意 Entity Framework 使用 Contains 时非常慢,尤其是在长列表中。

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

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 有效地进行这样的查询。