Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用foreach迭代IQueryable会导致内存不足异常_C#_Linq_Linq To Sql - Fatal编程技术网

C# 使用foreach迭代IQueryable会导致内存不足异常

C# 使用foreach迭代IQueryable会导致内存不足异常,c#,linq,linq-to-sql,C#,Linq,Linq To Sql,我正在使用foreach/IQueryable和linqtosql遍历一个很小的(~10GB)表。 看起来像这样: using (var conn = new DbEntities() { CommandTimeout = 600*100}) { var dtable = conn.DailyResults.Where(dr => dr.DailyTransactionTypeID == 1); foreach (var dailyResult in dtable)

我正在使用foreach/IQueryable和linqtosql遍历一个很小的(~10GB)表。 看起来像这样:

using (var conn = new DbEntities() { CommandTimeout = 600*100})
{
     var dtable = conn.DailyResults.Where(dr => dr.DailyTransactionTypeID == 1);
     foreach (var dailyResult in dtable)
     {
        //Math here, results stored in-memory, but this table is very small. 
        //At the very least compared to stuff I already have in memory. :)
     }
}

VisualStudio调试器在foreach循环的基础上运行一段时间后抛出内存不足异常。我假设dtable的行没有被刷新。怎么办

您将~10GB称为smallish?你很有幽默感

您可以考虑在块中加载行,也可以是分页。

conn.DailyResults.Where(dr => dr.DailyTransactionTypeID == 1).Skip(x).Take(y);

当枚举时,
IQueryable
dtable
将尝试将整个查询结果加载到内存中。。。在foreach循环的任何迭代之前。在foreach循环的迭代过程中,它不会加载一行。如果您想要这种行为,请使用。

使用DataReader是一种倒退,除非有办法在LINQ中使用它。我以为我们是想摆脱阿多

上述建议的解决方案是可行的,但确实很难看。这是我的密码:

int iTake = 40000;
int iSkip = 0;
int iLoop;
ent.CommandTimeout = 6000;
while (true)
{
  iLoop = 0;
  IQueryable<viewClaimsBInfo> iInfo = (from q in ent.viewClaimsBInfo
                                       where q.WorkDate >= dtStart &&
                                         q.WorkDate <= dtEnd
                                       orderby q.WorkDate
                                       select q)
                                      .Skip(iSkip).Take(iTake);
  foreach (viewClaimsBInfo qInfo in iInfo)
  {
    iLoop++;
    if (lstClerk.Contains(qInfo.Clerk.Substring(0, 3)))
    {
          /// Various processing....
    }
  }
  if (iLoop < iTake)
    break;
  iSkip += iTake;
}
int-iTake=40000;
int-iSkip=0;
int iLoop;
ent.CommandTimeout=6000;
while(true)
{
iLoop=0;
IQueryable iInfo=(来自ent.viewClaimsInfo中的q
其中q.WorkDate>=dtStart&&

q、 WorkDate我建议改用SQL修改此数据。

使用.AsNoTracking()-它告诉DbEntities不要缓存检索到的行

using (var conn = new DbEntities() { CommandTimeout = 600*100})
{
     var dtable = conn.DailyResults
                .AsNoTracking()      // <<<<<<<<<<<<<<
                .Where(dr => dr.DailyTransactionTypeID == 1);
     foreach (var dailyResult in dtable)
     {
        //Math here, results stored in-memory, but this table is very small. 
        //At the very least compared to stuff I already have in memory. :)
     }
}
使用(var conn=new DbEntities(){CommandTimeout=600*100})
{
var dtable=conn.DailyResults

.AsNoTracking()//您已经在大于10GB的内存中存储了什么?您是说10MB吗?我在这台计算机上有16GB的内存,但至少有一半的内存被任何windows膨胀加SQL缓存使用。我无法将10GB放入内存,所以我用完了它。令我惊讶的是IQueryable检索到了整个表……我希望它能够恢复一次编译一行或少量行。我似乎已经能够通过将编译目标更改为x64而不是x86来解决这个问题,这会占用我机器上更多的内存。但是,我在foreach循环中迭代的数据不是很大,所以我认为循环中的内容不会被垃圾收集当然。除非OP有20GB的RAM,否则这是处理这种情况的唯一方法。我不确定,你的意思是告诉我这种分页方法是有效的吗?我只是很惊讶iQuerable想要将内容加载到内存中。我的意思是,为什么不让它成为某种数组,向无助的程序员表明其讨厌的意图呢。:)现在我已经将表导出到一个平面文件中,并逐行读取。下次我将像专业人员一样使用DataReader:)那么,在迭代iqueryable时为什么会出现错误(已经有一个打开的DataReader与此命令关联,必须先关闭)当你在执行第一个查询的结果的同时执行另一个查询的时候,我不确定我是否遵循一些奇怪的部分,但是这个想法是:=查询,跳过,取。很奇妙,除了现在你得到了一个不同的问题的部分-要花多少时间。也欢迎到StAccExoLoT!“奇怪的部分”,虽然“奇怪”似乎是我的中间名:)我回到了ADO.Net,不幸的是,如前所述。