LINQ到实体执行顺序/时序问题

时间:2010-12-29 15:39:48

标签: linq-to-entities

我有两个长查询,每个类型都是“typeViewRequest”

   results1 = ..... (timeout)

   results2=..... (timeout)

现在.....

案例1 --------------------------------------------- --------------------------------

如果我这样做

   results1 = ..... .Take(countRecordsToShow/2)
   results2 = ..... .Take(countRecordsToShow/2)

然后我说

   results = results1.Union<typeViewRequest>(results2);

它工作正常。使用分页的网格显示了countRecordsToShow记录,这里没问题。

案例2 --------------------------------------------- --------------------------------

如果我这样做

   results1 = ..... 
   results2 = .....

然后我说

   results = results1.Union<typeViewRequest>(results2).Take(countRecordsToShow)

然后我有一个超时。为什么?因为我的gridview显然需要获取记录数,才能设置其分页。我的SelectCountMethod,名为getPreviousRequestsSelectCount,只是说

public int getPreviousRequestsCountFromDB(String name, DateTime dtStart, DateTime dtEnd, ReportedBy_Filter reportedBy, Status_Filter status, ReportType_Filter type, int countRecordsToShow, int userID)
{
return getPreviousRequests(companyNameLike: name, dtStart: dtStart, dtEnd: dtEnd, reportedBy: reportedBy, status: status, type: type, sortExpression: null, userID: userID, countRecordsToShow: countRecordsToShow).Count();
}

在get1reviousRequests内部,在Case1中,应用了TAKE(如“案例2”中所述):

results = results1.Union<typeViewRequest>(results2).Take(countRecordsToShow)

虽然countRecordsToShow只有20,但它超时了!我缓存那个数字,直到过滤标准改变,是的,但仍然......: - ((

其他问题:我也有一些过滤要做。这种过滤应该在BOTH分支上进行,如下所示:

   results1 = .....  Where (something1)

   results2 = ..... .Where (something2)

但如果我说,就像案例1一样,

   results1 = .....  Where (something1).Take(countRecordsToShow/2)

   results2 = ..... .Where (something2).Take(countRecordsToShow/2)

这会切断我的过滤数据集,我担心 - 让我们说countRecordsToShow = 20.如果results1(由something1过滤)有15条记录,我只需要10.如果results2(由something2过滤)比方说,5条记录,我会拿5.然后UNION将有15条而不是20条记录。

通常我应该这样做,就像在Case2中一样:

   results1 = .....  Where (something1)

   results2 = ..... .Where (something2)

然后说

results = results1.Union<typeViewRequest>(results2).Take(countRecordsToShow)

如果过滤的results1.Union(results2)有25条记录但countRecordsToShow为20,那么就这样吧。我只想说数据集不完整,需要额外的过滤。

但是因为我必须在UNION之前修剪数据集,否则这会影响我的过滤!

我预计结果查询将首先拉出每个分支,然后执行UNION,然后过滤,然后在最后修剪。

好吧,显然如果我在做其他事情之前没有修剪每个分支,我会暂停。

这一切如何运作?我非常困惑。我甚至无法使用COUNT来查找我应该期望的记录数,并且因此表现得很好,因为COUNT枚举了数据集,因此给了我一个超时。

请问有什么选择? (没有创建sprocs,我不允许这样做)。现在我发现的唯一“解决方案”是case1 - 在联盟之前向每个分支应用TAKE子句,但正如我所提到的那样,在过滤方面会出错。

我在这里做错了什么?我真的需要配合“逻辑残障”案例1吗?请帮忙!

谢谢

亚历

注意:

我测试了这个:如果执行了行

results = results1.Union<typeViewRequest>(results2).Take(20)

我试着检查

results.count()
在即时窗口中,它超时了!它没有看到它有.Take(20)条款吗?为什么首先必须枚举所有记录?我应该列举到极限,20,然后停止。显然它一直枚举到大约250.000,然后将结果集修剪为20。

注意:我在这里读到:Exploring LINQ Query Operators and Differed Execution Plan TAKE和UNION都被定义了。那么....为什么不将TAKE集成到查询中,而是应用于事后呢?

1 个答案:

答案 0 :(得分:0)

我不能说我理解你的整个帖子,但我最近的经历可能适用于此。 。 。因为你有零帖子。 。 。我试试看。

我有这样的事情:

var results = from ... ;
foreach(results)
{
    do something
}

工作得很好,但运行了四分钟,因为结果包含了400万条记录。由于我是LINQ / EF4 newb,我将其更改为:

var results = from<blah>;
int count = 0;
foreach(results)
{
    if (count++ > 100)
        break;
    do something
}

执行此操作后,它会在第100条记录之后的foreach语句中超时并终止foreach循环。

经过多次阅读和实验后我得出的结论是查询将完成!!!

不管你喜不喜欢,Query都会运行完成。

因此,在原始格式中,我通过逐个获取每个小块来在foreach循环中运行查询。这样做永远不会超时,因为解析结果中的下一个项目非常快。

但是,一旦我输入了break语句,在第100条记录之后,查询试图在单个gulp中完成自身,因此它将超时,因为在单个调用获取的超时中无法接受400万条记录

结果即将超出范围并被销毁的事实并不重要。查询必须完成。 。 。使用与否。 。 。必须完成查询。

这是一项非常令人沮丧但又具有启发性的练习。