Entity Framework lambda 扩展方法在啥时候将查询发送到数据库?

Posted

技术标签:

【中文标题】Entity Framework lambda 扩展方法在啥时候将查询发送到数据库?【英文标题】:At what point does Entity Framework lambda extension method send the query to database?Entity Framework lambda 扩展方法在什么时候将查询发送到数据库? 【发布时间】:2019-06-18 17:30:03 【问题描述】:

我试图弄清楚如何优化一些数据库查询,以便它们使用我们数据库中内置的索引,并快速提取所请求的数据。

我想了解的是,在下面的代码中,IQueryable 在什么时候被翻译成 SQL,并发送到数据库进行检索。我在下面的尝试是尝试利用现有索引来缩小数据集,然后对较小的数据集执行额外的更复杂和更少索引的操作。

我的直觉是,在我调用 ToListAsync() 之前,调用实际上并没有进入数据库(因此我的方法有点毫无意义),但我不确定。

对于上下文,下面的代码是一个控制器动作,并包含在一些异常处理中。为了简单起见,去掉了所有这些。

                var shift_Offers = db.Shift_Offers.Include(c => c.Callout)
                                                    .Where(x => x.Callout.shift_date_new >= today
                                                        && x.employee_id_fk == id
                                                        && x.offer_timestamp != null);

                //do the complex work on the data set once we've gotten the main dataset
                shift_Offers = shift_Offers.Where(x => ((x.Callout.employee_id_fk ?? -1) == id ||
                                                            (x.Callout.employee_id_fk ?? -1) == -1)
                                                        && (x.Callout.status.Contains(CalloutStatus.inprogress)
                                                            || x.Callout.status.Contains(CalloutStatus.inprogressWaitingNext)
                                                            || x.Callout.status.Contains(CalloutStatus.stopped)
                                                            || x.Callout.status.Contains(CalloutStatus.finishedSucceeded)
                                                            || x.Callout.status.Contains(CalloutStatus.finishedFailed)));

                //do work on the shift offer table last, once the data set is smallest
                shift_Offers = shift_Offers.Where(x => !x.offer_status.Contains(ShiftOfferStatus.NotYetOffered));

                Debug.WriteLine(shift_Offers.AsQueryable().ToString());
                List<Shift_Offer> shos = await shift_Offers.ToListAsync();
                return View(shos);

【问题讨论】:

docs.microsoft.com/en-us/dotnet/framework/data/adonet/ef/… 是的,当您使用数据或执行 ToList() 或类似操作时。我认为前 2 个代码块可能是一个并且是相同的......就像 2 组带有 AND 的条件。 您可以执行第一个块,选择 shift_offers 的 ID,然后执行 ToList()。然后,在您的第二个块中添加一个条件,其中 ID 包含在上一个列表中。 @Romias - 我实际上需要做的是在第一个块之后做一个 ToList,然后在列表上的应用程序中做其余的事情。第一个代码块是索引优化的,所以即使在最坏的情况下它也能很快地提取数据。其余的不是,这就是我的查询卡住的原因。 是的,我认为我们在同一页上。 【参考方案1】:

在以下情况下对数据库执行查询:

它由 foreach (C#) 或 For Each (Visual Basic) 枚举 声明。 由ToArray等集合操作枚举, ToDictionary 或 ToList。 在最外层指定了诸如 First 或 Any 等 LINQ 运算符 查询的一部分。 调用以下方法: DbSet、DbEntityEntry.Reload 和 Database.ExecuteSqlCommand。

在您的情况下,当您调用 ToListAsync() 方法时。作为一般规则,只要您使用 IQueryable 对象,就不会执行查询,一旦您尝试将其强制转换为其他对象,就会进行查询。

来源:https://docs.microsoft.com/en-us/ef/ef6/querying/

【讨论】:

是的,我刚刚从 Adam 链接的文档中提取了它。太棒了。

以上是关于Entity Framework lambda 扩展方法在啥时候将查询发送到数据库?的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework lambda 扩展方法在啥时候将查询发送到数据库?

如何使用 Entity Framework Core 2.0 上的 lambda 语法在 LINQ 中实现 LEFT OUTER JOIN?

Entity Framework 全面教程详解(转)

MVC5 Entity Framework学习之Entity Framework高级功能

Entity Framework 学习系列 - 认识理解Entity Framework

Entity Framework Code-First(23):Entity Framework Power Tools