我有这个加入:
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,只有四行custID
等于ID
表中的客户对象Service
。当我使用ToList()
或Count()
时,使用的内存会快速超过1GB,而我的outMfory异常。你能告诉我这段代码有什么问题吗?提前谢谢。
答案 0 :(得分:2)
原因是你并没有真正在服务器上执行加入。 custFinal
正如你所说的只是内存列表,而不是数据库表或查询。所以它是IEnumerable
,而不是IQueryable
。当您执行加入时 - 它会调用IEnumerable.Join
,而不是IQueryable.Join
方法。后者将构建一个查询,但前者只是将所有参数拉入内存并在内存中执行连接。所以在结果中 - 整个Service
表被拉入内存并加入那里(很容易检查你是否记录了EF上下文查询 - 你会看到它只是从服务查询中执行select all。)
如果更改连接中的参数顺序以便执行IQueryable.Join
- 这也不会有帮助,因为无论如何都无法将具有内存列表的数据库表与实体框架连接起来。所以你必须找到另一种方式,例如:
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,没有实体框架(如果你使用SQL服务器,你还需要在sql server中创建自定义表类型)。