简体   繁体   English

Linq2Entities包含在“跳过/获取”中-加载问题

[英]Linq2Entities Include with Skip / Take - load issue

Note: I know there are a number of questions around for issues with Linq's .Include(table) not loading data, I believe I have exhausted the options people have listed, and still had problems. 注意:我知道Linq的.include(table)不能加载数据存在很多问题,我相信我已经用光了人们列出的选项,但仍然有问题。

I have a large Linq2Entities query on an application I'm maintaining. 我要维护的应用程序上有一个大型Linq2Entities查询。 The query is built up as such: 查询是这样构建的:

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

Then predicates are built up depending on various business logic, such as: 然后根据各种业务逻辑来构建谓词,例如:

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);
}

Note - there is always a sort order provided. 注意-始终提供排序顺序。

Originally the included tables were set at the beginning, after reading articles such as the famous Tip 22 , so now they are done at the end (which didn't fix the problem): 最初,包含的表格是在阅读著名的Tip 22之类的文章后开始设置的,所以现在它们在结尾处完成(这不能解决问题):

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

Seemingly at random (approximately for every 5000 users of the site, this issue happens once) the RelatedTable data won't load. 似乎是随机的(大约每站点5000个用户,此问题就会发生一次),不会加载RelatedTable数据。 It can be brute forced by calling load on the related table. 可以通过在相关表上调用load来强行使用它。 But even the failure to load isn't consistent, I've run the query in testing and it's worked, but most of the time hasn't, without changing any code or data. 但是,即使加载失败也不是始终如一的,我已经在测试中运行了查询并使其正常运行,但大多数情况下没有这样做,而没有更改任何代码或数据。

It is fine, when the skip and take aren't included, and the whole dataset is returned, but I would expect the skip and take to be done on the complete dataset - it certainly appears to be from profiling the SQL... 很好,当不包括跳过和获取,并且返回整个数据集时,但是我希望跳过和获取在完整的数据集上完成-这肯定是由于对SQL进行概要分析...

UPDATE 16/11/10: I have profiled the SQL against a problem data set, and I've been able to reproduce the query failing about 9/10 times, but succeeding the rest. 更新16/11/10:我已经针对问题数据集对SQL进行了概要分析,并且能够重现失败9/10次的查询,但成功了其余部分。 The SQL being executed is identical when the query fails or succeeds except, as expected, for the parameters passed to the SQL. 查询失败或成功时,所执行的SQL相同,只是传递给SQL的参数与预期的不同。

The issue has been solved with the following change, but the question remains as to why this should be. 通过以下更改已解决了该问题,但问题仍然是为什么。

Failing - get LINQ to handle the rows: 失败-使LINQ处理行:

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

Working - enumerate the data then get the rows: 工作-枚举数据然后获取行:

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

Unfortunately the SQL this query creates contains some sensitive schema data so I can't post it, it is also 1400 lines long, so I wouldn't subject the public to it anyway! 不幸的是,该查询创建的SQL包含一些敏感的模式数据,因此我无法发布它,它的长度也为1400行,因此无论如何我都不会使公众服从它!

The sole effect of Take() is to change the generated SQL. Take()的唯一作用是更改生成的SQL。 Other than that, the Entity Framework does not care about it at all. 除此之外,实体框架根本不关心它。 Same for .Skip() . .Skip()相同。 It's hard to believe that this would have an effect on query materialization (although stranger things have happened). 很难相信这会对查询的实现产生影响(尽管发生了一些奇怪的事情)。

So what could be causing this behavior? 那么,什么可能导致这种行为? Off the top of my head: 脱离我的头顶:

  1. A bug in your application or mapping which is causing an incorrect query to be generated. 您的应用程序或映射中的错误导致生成不正确的查询。
  2. A bug in the Entity Framework which would cause returned data to be materialized into objects incorrectly in certain circumstances. 实体框架中的错误,在某些情况下会导致将返回的数据错误地物化为对象。
  3. Bad data in your database. 数据库中的错误数据。
  4. A bug in your database's SQL parser. 数据库的SQL解析器中的错误。

I don't think you're going to get a lot further with this until you can capture the generated SQL and run it yourself. 在您可以捕获生成的SQL并自己运行它之前,我认为您不会对此进一步了解。 This is actually not terribly hard, as you can set up a SQL profiler with an appropriate filter. 实际上,这并不困难,因为您可以使用适当的过滤器来设置SQL事件探查器。 If you find that the generated SQL is different in the buggy case, you can work backwards from there. 如果发现在错误的情况下生成的SQL是不同的,则可以从那里向后进行处理。 If you find that the generated SQL is identical in the buggy case, the next step would be to look at the rows returned, preferably in the same context as the application ran it. 如果发现在错误的情况下生成的SQL是相同的,那么下一步将是查看返回的行,最好是在应用程序运行它的上下文中。

In short, I think you just have to keep tweaking your SQL profiling until you have the information you need. 简而言之,我认为您只需调整SQL配置文件,直到获得所需的信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM