如何使用 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();
Driver
和 Building
表都有大约 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();
最初我有这样一个列表:
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();
Driver
和 Building
表都有大约 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();