Linq2Entities包括Skip / Take - load问题

时间:2010-10-14 13:51:46

标签: c# entity-framework linq-to-entities

注意:我知道Linq的问题存在很多问题.Include(表)没有加载数据,我相信我已经用尽了人们列出的选项,但仍然有问题。

我正在维护的应用程序上有一个很大的Linq2Entities查询。查询构建如下:

IQueryable<Results> query = context.MyTable
    .Where(r =>
    r.RelatedTable.ID == 2 &&
    r.AnotherRelatedTable.ID == someId);

然后根据各种业务逻辑构建谓词,例如:

if (sortColumn.Contains("dob "))
{
    if (orderByAscending)
        query = query.OrderBy(p => p.RelatedTable.OrderByDescending(q => q.ID).FirstOrDefault().FieldName);
    else
        query = query.OrderByDescending(p => p.RelatedTable.OrderByDescending(q => q.ID).FirstOrDefault().FieldName);
}

注意 - 始终提供排序顺序。

最初,在阅读了着名的Tip 22之类的文章之后,所包含的表格被设置在开头,所以现在它们在最后完成(这不能解决问题):

var resultsList = (query.Select(r => r) as ObjectQuery<Results>)
    .Include("RelatedTable")
    .Include("AnotherRelatedTable")
    .Skip((page - 1) * rowsPerPage)
    .Take(rowsPerPage);

似乎是随机的(大约每5000个网站用户,这个问题发生一次),不会加载RelatedTable数据。可以通过在相关表上调用load来强制强制它。但即使加载失败也不一致,我在测试中运行查询并且它有效,但大部分时间都没有,无需更改任何代码或数据。

很好,当不包括skip和take时,返回整个数据集,但我希望跳过并在完整的数据集上完成 - 它肯定似乎来自分析SQL。 ..

更新16/11/10:我已针对问题数据集分析了SQL,并且我已经能够重现查询失败大约9/10次,但接下来其余的。当查询失败或成功时,正在执行的SQL是相同的,除非正如预期的那样,传递给SQL的参数。

这个问题已经通过以下改变得到了解决,但问题仍然是为什么会这样。

失败 - 让LINQ处理行:

var resultsList = (query.Select(r => r) as ObjectQuery<Results>)
    .Include("RelatedTable")
    .Include("AnotherRelatedTable")
    .Skip((page - 1) * rowsPerPage)
    .Take(rowsPerPage)
    .ToList();

工作 - 枚举数据,然后获取行:

var resultsList = (query.Select(r => r) as ObjectQuery<Results>)
    .Include("RelatedTable")
    .Include("AnotherRelatedTable")
    .ToList()
    .Skip((page - 1) * rowsPerPage)
    .Take(rowsPerPage);

不幸的是,这个查询创建的SQL包含一些敏感的架构数据,因此我无法发布它,它也是1400行,所以无论如何我都不会让公众接受它!

1 个答案:

答案 0 :(得分:2)

Take()的唯一影响是更改生成的SQL。除此之外,实体框架根本不关心它。 .Skip()也是如此。很难相信这会对查询实现产生影响(虽然发生了奇怪的事情)。

那么可能导致这种行为?在我的头顶:

  1. 您的应用程序或映射中的错误,导致生成错误的查询。
  2. 实体框架中的一个错误,它会导致在某些情况下错误地将返回的数据实现为对象。
  3. 数据库中的错误数据。
  4. 数据库的SQL解析器中的错误。
  5. 我认为你不会进一步了解这个问题,直到你能够捕获生成的SQL并自己运行它。这实际上并不十分困难,因为您可以使用适当的过滤器设置SQL事件探查器。如果您发现生成的SQL在错误的情况下是不同的,您可以从那里向后工作。如果您发现生成的SQL在错误情况下是相同的,那么下一步将是查看返回的行,最好是在与应用程序运行它相同的上下文中。

    简而言之,我认为您必须不断调整SQL分析,直到获得所需信息为止。