【发布时间】:2017-07-09 23:11:46
【问题描述】:
我有一个问题,在循环我的 foreach 语句时,我的应用程序返回超时错误。请注意,我无法修改或查看正在查询的表。
IEnumerable<MyTable> TContextData;
if (!string.IsNullOrEmpty(id)
|| !string.IsNullOrEmpty(name)
|| !string.IsNullOrEmpty(cell)
)
{
TContextData = (from e in db.mytable
where (!String.IsNullOrEmpty(e.id))
select e);
}
else
{
TContextData = null;
}
List<EachC> mDatalist = new List<EachC>();
if (TContextData != null)
{
foreach (var i in TContextData.ToList())
{
EachMR EachM = new EachMR();
EachM.Feature = i.TRuid;
EachM.Feature2 = i.TRuid2;
EachM.Feature3 = i.TRuid3;
EachM.Date = GetInnerTextfromXML(EachM.Feature3, "/Sections/Multiple/Functions/Group/Date");
mdatalist.Add(EachM);
}
}
大约有 40K 行需要迭代。有没有办法可以提高效率?
错误消息:System.Data.Entity.dll 中出现“System.OutOfMemoryException”类型的异常,但未在用户代码中处理
我已将 Context 中的超时时间增加到
((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 0;
但无济于事,因为它只是掩盖问题。
【问题讨论】:
-
您需要
mytable行的全部内容吗?每一行真的需要受到“做事”的影响吗?e.id可以是空的,或者只是空的,还是真的需要两个检查?如果您在开始迭代之前.ToList()第二个查询有什么不同吗?您是否需要将更改保存回数据库?您是否在“do stuff”中访问mytable的子表(注意在for循环中延迟执行的查询)?您是否对此进行了分析以查看正在运行的 SQL?您可能会执行 40,000 个查询而不是 1 个。 -
为什么
.Take(1)会阻止你的foreach超时? - 我的意思是,显然它只会返回一行,但为什么你会得到一行而不是做一个空(或空)检查? -
您的应用程序是如何托管的,需要多长时间才能超时?此外,您的问题可能不在于您展示的 linq,而在于您尚未向我们展示的
#Do Stuff部分。您需要分析您的代码,尤其是#Do Stuff 部分,并查看哪个部分花费的时间过长 -
您的两个查询是同一件事。检查您的连接字符串中是否启用了
MultipleResultSets,以防延迟执行使您绊倒。尝试 .ToList() 并将 40k 记录拉入内存以避免这种情况。如果数据过多,请限制您引入的内容。 -
完整的错误信息是什么?将其包装在 Try/Catch 中并在异常上调用
ToString()并为我们提供完整的异常。