【问题标题】:IQueryable: Select new triggers eager loading?IQueryable:选择新的触发器急切加载?
【发布时间】:2022-10-14 21:33:42
【问题描述】:

我试图了解如何执行 linq 查询。

据我所知,IQueryable 查询与过滤器和选择一起在服务器端进行评估,并且仅在调用 ToList() 或 First() 方法时执行。

但是,我无法理解如何评估以下查询。是在客户端还是在服务器端评估“选择新”?

Select(x=> new Note) 是否触发了急切加载?

IQueryable<Note> query = db.Notes
                           .Where(x => Id == someId)
                           .Select(c => new Note 
                                            {
                                                Title = x.Title
                                                Id = x.NoteId,
                                            });

【问题讨论】:

  • 它并没有真正在服务器端执行。在客户端,它形成一个相应的 SQL 查询并发送它。在您的情况下,select 语句定义要检索的表列(Title 和 NoteId),并且该对象将在客户端创建。
  • 就像 Oliver 所说的一切都在客户端执行,IQueryable 只是将执行延迟到需要的时候。因此,您的投影 (Select) 将在生成的 SQL 中考虑在内
  • 见副本。关键是全部的表达式 (query) 被翻译成 SQL。 SQL 由数据库执行。但也可以看看:learn.microsoft.com/en-us/ef/core/querying/client-eval
  • @GertArnold,为什么被迫关闭?刚刚准备好的解释,与什么都不解释的文档无关。
  • @paradise 什么时候执行?

标签: c# linq select entity-framework-core


【解决方案1】:

在您的情况下,Select new 是如何将 DbDataReader 字段映射到 Note 对象的指令。 x.Title 之类的成员访问部分被转换为dbReader.GetString(0) 之类的阅读器指令。

内部 LINQ 转换器生成用于检索数据的 SQL

SELECT 
    x.Title,
    x.NoteId
FROM Notes x
WHERE x.Id = @someId

并生成LambdaExpression(示意图)

(DbDataReader dr) => new Note
{
    Title = dr.GetString(0),
    Id = dr.GetInt32(1)
}

然后这个LambdaExpression 被编译和缓存。当 LINQ Provider 通过ToList()、ToArray() 等执行查询时,生成的 SQL 被发送到数据库并开始枚举 DataReader 的过程。对于在编译的 lambda 之上应用的每个 DataReader 记录。它来自IQueryable&lt;Note&gt;(服务器端)IEnumerable&lt;Note&gt;(客户端)。

这是非常简单的解释在引擎盖下做了什么。

【讨论】:

  • 谢谢@SvyatoslavDanyliv。它在回答我的问题。如果您不介意,您能否提供一些有助于拓宽我知识的资源。
猜你喜欢
  • 1970-01-01
  • 2019-07-29
  • 1970-01-01
  • 2014-10-31
  • 1970-01-01
  • 2021-12-03
  • 2014-09-27
  • 2015-05-08
  • 1970-01-01
相关资源
最近更新 更多