如何使用 LINQ 加入列表和大 lists/tables

How to join a list and large lists/tables using LINQ

最初我有这样一个列表:

List<Car> cars = db.Car.Where(x => x.ProductionYear == 2005).ToList();

然后我尝试像这样使用 LINQ 将此列表与两个大表连接起来:

var joinedList = (from car in cars
                  join driver in db.Driver.ToList() 
                    on car.Id equals driver.CarId
                  join building in db.Building.ToList() 
                    on driver.BuildingId equals building.Id
                  select new Building
                  {
                     Name = building.Name;
                     Id = building.Id;
                     City = building.City;
                  }).ToList();

DriverBuilding 表都有大约 100 万行。当我 运行 这个连接时,我得到了内存不足异常。我怎样才能使这个加入工作?我应该在数据库上进行连接操作吗?如果是,我如何将 cars 列表携带到数据库?提前致谢。

即使您删除了连接中的 .ToList() 调用,您的代码仍将提取所有数据并在内存中执行连接,而不是在 SQL 服务器中。这是因为您在加入中使用了本地列表 cars。以下应该可以解决您的问题:

var joinedList = (from car in db.Car.Where(x => x.ProductionYear == 2005)
                  join driver in db.Driver 
                    on car.Id equals driver.CarId
                  join building in db.Building 
                    on driver.BuildingId equals building.Id
                  select new Building
                  {
                     Name = building.Name;
                     Id = building.Id;
                     City = building.City;
                  }).ToList();

如果您希望在结果中获得太多记录,您可以删除最后一个 .ToList() 并做一些 paging

首先,在使用 LINQ 时永远不要尝试 ToList()(可以),但请确保仅在非常罕见的情况下尽可能少地使用 ToList()。 每次当 table 包含许多行时,您将得到 OutOfMemoryException。 因此,这是您的问题的代码:

var joinedList = (from car in db.Car.GetQueryable().Where(x => x.ProductionYear == 2005)
              join driver in db.Driver.GetQueryable() on car.Id equals driver.CarId
              join building in db.Building.GetQueryable() on driver.BuildingId equals building.Id
              select new Building
              {
                 Name = building.Name;
                 Id = building.Id;
                 City = building.City;
              }).ToList();

即使您删除了 .ToList() 替换为 .AsQueryable()

AsQueryable 比 ToList 和 AsEnumerable 更快

  • 如果你创建一个IQueryable,那么查询可能会被转换成sql 和数据库服务器上的 运行

  • 如果你创建一个IEnumerable,那么所有的行都会被拉入
    运行查询前的内存作为对象。

  • 在这两种情况下,如果您不调用 ToList() 或 ToArray(),则查询
    每次使用时都会执行,所以,比如说,你有一个
    IQueryable 并从中填充 4 个列表框,然后查询将是 运行 对数据库4次。

所以遵循 Used Linq 查询

var joinedList = (from car in db.Car.Where(x => x.ProductionYear == 2005).AsQueryable()
              join driver in db.Driver.AsQueryable() 
                on car.Id equals driver.CarId
              join building in db.Building.AsQueryable() 
                on driver.BuildingId equals building.Id
              select new Building
              {
                 Name = building.Name,
                 Id = building.Id,
                 City = building.City,
              }).ToList();