我有以下连接声明:
var query = from holding in dHoldList
join client in clientList on
new { holding.ClientNo }
equals new { client.ClientNo } into clj
from cl in clj.DefaultIfEmpty()
join matter in matterList on
new { holding.ClientNo }
equals new { matter.ClientNo } into mlj
from ml in mlj.DefaultIfEmpty()
join stk in stockList on
new { holding.Sedol }
equals new { stk.Sedol } into slj
from sl in slj.DefaultIfEmpty()
select
new GeneralHoldingsReport()
{
ClientNo = holding.ClientNo,
Depot = holding.Depot,
HoldingSedol = holding.Sedol,
Value = holding.ValueOfStock,
NoOfUnits = holding.QuantityHeld,
ClientName = (cl == null ? null : cl.ClientName),
CountryOfResidence = (cl == null ? null : cl.CountryOfResidence),
BG = (cl == null ? null : cl.BusinessGetter),
ClientStockValue = (ml == null ? 0 : ml.FullValueOfPortfolio),
StockName = (sl == null ? null : sl.R1.Trim() + " " + sl.R2.Trim())
};
var reportList = query.ToList();
然而,当它运行时,我收到内存不足异常错误。
我要求dHoldList是主表,所有其他表都保留在其中(即如果数据在与dHoldList中的每个记录相关的其他表中匹配,则返回数据,如果不是空白的话。)我相信我我这样做是正确的,但显然不是。
这些列表中的每一行都包含大约300k行,除了客户端只有30k,因此可能会导致一些问题。
答案 0 :(得分:2)
您正在联接中实例化大量无用的匿名类型。您可以按如下方式编写它们:
join client in clientList on holding.ClientNo equals client.ClientNo into clj
也许这已经解决了你的记忆问题? 这仅适用于LINQ to Objects。如果您的查询被转换为SQL,就像EF或LINQ to SQL一样,这些匿名类型将不会被创建。
考虑重构查询以使其更具可读性:
var query =
from holding in dHoldList
join client in clientList on holding.ClientNo equals client.ClientNo into clj
join matter in matterList on holding.ClientNo equals matter.ClientNo into mlj
join stk in stockList on holding.Sedol equals stk.Sedol into slj
from cl in clj.DefaultIfEmpty()
from ml in mlj.DefaultIfEmpty()
from sl in slj.DefaultIfEmpty()
select new GeneralHoldingsReport()
{
ClientNo = holding.ClientNo,
Depot = holding.Depot,
HoldingSedol = holding.Sedol,
Value = holding.ValueOfStock,
NoOfUnits = holding.QuantityHeld,
ClientName = (cl == null ? null : cl.ClientName),
CountryOfResidence = (cl == null ? null : cl.CountryOfResidence),
BG = (cl == null ? null : cl.BusinessGetter),
ClientStockValue = (ml == null ? 0 : ml.FullValueOfPortfolio),
StockName = (sl == null ? null : sl.R1.Trim() + " " + sl.R2.Trim())
};
这不会对内存占用产生任何影响,但会对可读性和可维护性产生影响。
如果我要编写代码来实现您的目标,特别是涉及到许多对象,我就不会使用join
。我会使用哈希表。这会快得多。
像这样(未经测试):
var clients = clientList.ToDictionary(x => x.ClientNo);
var matters = matterList.ToDictionary(x => x.ClientNo);
var stocks = stockList.ToDictionary(x => x.Sedol);
var reportList = new List<GeneralHoldingsReport>(dHoldList.Count);
Client client;
Matter matter;
Stock stock;
foreach(var holding in dHoldList)
{
if(!clients.TryGetValue(holding.ClientNo, out client))
client = null;
if(!matters.TryGetValue(holding.ClientNo, out matter))
matter = null;
if(!stocks.TryGetValue(holding.Sedol, out stock))
stock = null;
reportList.Add(new GeneralHoldingsReport()
{
ClientNo = holding.ClientNo,
Depot = holding.Depot,
HoldingSedol = holding.Sedol,
Value = holding.ValueOfStock,
NoOfUnits = holding.QuantityHeld,
ClientName = (client == null ? null :
client.ClientName),
CountryOfResidence = (client == null ? null :
client.CountryOfResidence),
BG = (client == null ? null :
client.BusinessGetter),
ClientStockValue = (matter == null ? 0 :
matter.FullValueOfPortfolio),
StockName = (stock == null ? null :
stock.R1.Trim() + " "
+ stock.R2.Trim())
});
}
如果每个客户编号有多个客户端或事项,并且每个sedol有多个库存,ToDictionary
的使用将导致崩溃。