一个简单的连接消耗太多内存 - LINQ

A simple join consumes too much memory - LINQ

我有这个加入:

var andlist = (from cust in custFinal
               join serv in db.Service on cust.ID equals serv.CustID
               select new JoinObj
               {
                   Name = cust.name,
                   ServiceID = serv.ID,
               });

custFinal 是仅包含一个对象的 Customer 列表。 db.Service 是一个 DbSet,在 Service table 中只有四行 custID 等于客户对象的 ID。当我使用 ToList()Count() 时,使用的内存很快超过 1GB,并且出现 outOfMemory 异常。你能告诉我这段代码有什么问题吗?提前致谢。

原因是你并没有真正在服务器上执行加入。 custFinal 如您所说,只是内存列表,而不是数据库 table 或查询。所以是IEnumerable,不是IQueryable。当您执行连接时 - 它调用 IEnumerable.Join,而不是 IQueryable.Join 方法。后者会构建一个查询,而前者只会将所有参数拉入内存并在内存中执行连接。所以结果 - 整个 Service table 被拉入内存并加入那里(很容易检查你是否记录了 EF 上下文查询 - 你会看到它只是执行 select 全部来自服务查询) .

如果您更改连接中参数的顺序以便执行 IQueryable.Join - 这也无济于事,因为您无法使用内存列表连接数据库 table Entity Framework 无论如何。所以你得另辟蹊径,比如:

var ids = custFinal.Select(c => c.ID).ToArray();
var matchingServices = db.Service.Where(serv => ids.Contains(serv.CustID)).Select(c => new {c.ServiceID, c.CustID}).ToArray();
// now filter `custFinal` based on `matchingServices`, in memory.

这将执行 CustID IN (...) 查询而不是联接。如果你坚持要加入 - 你将不得不使用原始 sql,没有 entity framework(你还需要在 sql 服务器中创建自定义 table 类型,如果您使用 SQL 服务器)。