【问题标题】:Linq2Entities Include with Skip / Take - load issueLinq2Entities Include with Skip / Take - 加载问题
【发布时间】:2011-04-25 10:25:09
【问题描述】:

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

我在维护的应用程序上有一个大型 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 来强制执行。但是即使加载失败也不一致,我已经在测试中运行了查询并且它工作了,但大多数时候没有,没有更改任何代码或数据。

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

2010 年 16 月 11 日更新:我已经针对问题数据集对 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 行长,所以我不会让公众接受它!

【问题讨论】:

  • 对不起,L2E...不知道我为什么要写 L2SQL!
  • 所以你是说 SQL 对于一个工作的查询请求和一个失败的查询请求是一样的?
  • 不幸的是,当我有数据存在这个问题时,成功的查询非常零星,我还没有设法在分析器中捕获 SQL 进行比较。但是我没有理由怀疑它会有所不同,因为在没有代码更改或谓词更改时观察到它。

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


【解决方案1】:

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

那么是什么可能导致了这种行为?在我脑海中浮现:

  1. 您的应用程序或映射中的错误导致生成不正确的查询。
  2. 实体框架中的一个错误会导致返回的数据在某些情况下被错误地具体化为对象。
  3. 您的数据库中有错误的数据。
  4. 数据库的 SQL 解析器中存在错误。

在您可以捕获生成的 SQL 并自己运行之前,我认为您不会对此有更进一步的了解。这实际上并不难,因为您可以使用适当的过滤器设置 SQL 分析器。如果您发现生成的 SQL 在有问题的情况下有所不同,您可以从那里向后工作。如果您发现生成的 SQL 在有问题的情况下是相同的,下一步将是查看返回的行,最好是在与应用程序运行它相同的上下文中。

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

【讨论】:

  • 我会将数字 3 移到数字 2 之上。如有疑问,请假设您的代码/数据错误,而不是您的工具。
  • 谢谢克雷格。我完全同意最可能的答案是我的数据。有趣的是,目前我已经通过将查询枚举到一个列表中来解决它,然后跳过并接受列表。这工作得很好......不确定这对这个问题意味着什么!在接下来的几天里,我将尝试再次分析好/坏查询,我原则上同意这是最好的选择,但可怕的是生成的 sql 有 2000 行长。有人为我认为的工作选择了错误的工具! :P
  • 2000 行?耸耸肩。它应该只是参数不同,对吧?如果没有,你可能发现了问题......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-03
  • 2011-10-16
  • 2012-06-12
相关资源
最近更新 更多