代码之家  ›  专栏  ›  技术社区  ›  Timbo

Linq2Entities包含跳过/加载问题

  •  0
  • Timbo  · 技术社区  · 14 年前

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

    我在维护的应用程序上有一个大型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个用户的网站,这个问题发生一次)相关的数据不会加载。它可以通过调用相关表上的load来强制执行。但即使加载失败也不一致,我已经在测试中运行了查询并且它已经工作了,但大多数情况下没有,没有更改任何代码或数据。

    很好,如果不包括skip和take,并且返回整个数据集,但是我希望skip和take是在整个数据集上完成的—这显然是从分析SQL开始的。。。

    2010年11月16日更新: 我已经针对一个有问题的数据集分析了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 回复  |  直到 14 年前
        1
  •  2
  •   Craig Stuntz    14 年前

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

    那又怎么样 导致这种行为?从我的头顶上:

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

    在捕获生成的SQL并自己运行它之前,我认为您不会对此有太多进展。这实际上并不十分困难,因为您可以使用适当的过滤器设置一个SQL分析器。如果您发现生成的SQL在buggy情况下是不同的,那么您可以从那里向后工作。如果您发现生成的SQL在错误情况下是相同的,那么下一步就是查看返回的行,最好是在应用程序运行它时的相同上下文中。