【问题标题】:How does Entity Framework entity loading work?Entity Framework 实体加载如何工作?
【发布时间】:2017-08-27 17:02:56
【问题描述】:

我一直在尝试制作自己的实体框架(用于个人项目并且出于对制作这样的东西需要什么的好奇)。

当我使用包含 700k 行和 5 列的数据表(名为 MassData)进行 Entity Framework 性能测试时,我遇到了一些特殊的问题,希望有人能向我解释。

运行以下测试:

var Context = new EntityFameworkContext();

var first = Context.MassData.Where(x => x.Id == 1);

var firstFifty = Context.MassData.Where(x => x.Id < 50).ToArray();

上下文创建需要 35 毫秒,获取 first 大约需要 215 毫秒,获取 firstFifty 需要 14 毫秒。

删除'first',得到'firstFifty'大约需要210ms。

如果我将'first' 查询切换为选择所有内容的Where(),结果是相同的(仍然没有迭代)。

我的第一个想法是,这是在 DbSet 中加载惰性数据的某种情况,第一个查询枚举下一个访问的数据(即使第一个查询没有遍历任何内容)。这可以解释为什么无论查询如何,第一个总是至少需要 200 毫秒,而第二个运行速度就像没有数据库连接一样快(“firstFifty”作为 SQL 查询运行至少需要 25 毫秒,超过我在这里看到的 15 毫秒)。

除了加载所有 MassData 需要 5 秒。只需阅读它大约需要2,5。因此它不能加载所有内容,但显然加载的内容超出了第一个查询所需的内容。所以很明显我错过了一些东西。

有人能解释一下为什么

var first = Context.MassData.Where(x => x.Id == 1);

查询加快了

var firstFifty = Context.MassData.Where(x => x.Id < 50).ToArray();

查询?


编辑:

事实证明,这与延迟加载完全无关。第一个查询打开连接,并且(我认为)执行并存储针对数据库表的实体类型的验证。然后第二个查询不必打开连接或做任何验证,在这种情况下,第二个查询的持续时间匹配,一切都有意义。


编辑 2:

修改了标题,以更好地匹配问题最终的真正含义(延迟加载如何工作 => 实体加载如何工作)。

【问题讨论】:

  • 这与延迟加载无关。

标签: c# sql entity-framework


【解决方案1】:

因为您仍在加载实体类型及其先决条件。无论您要查询什么。 EF 的 Lambda 表达式仍然是 SQL,具有从 Lambda 到 String 子句和语句的转换。因此,第一个缓慢不是来自查询,而是来自 EF 初始设置。

请记住,您仍在创建 EF 的实例,因此它会占用一些运行时进程。然后剩下的就是 Query Fetching 时间。由于 CLR 过程,这当然是不可避免的过程。

所以,一般来说。第二个查询已为查询做好准备,因为在您设置 EF 的模型中仍在使用,但是当垃圾收集决定它不会在任何地方使用时,您对下一个会话的查询将在EF 的开始初始化。 “意味着您与数据库的连接仍处于打开状态”就这么简单。

【讨论】:

  • “意味着您与数据库的连接仍处于打开状态”我没有想到,您是对的。使用 SqlDataReader,在不测量打开连接所需的时间的情况下,读取结果并映射它们需要 13ms,大约与 EF 所需的时间相同。谢谢!
【解决方案2】:

有一些工具可以显示 sql server 活动,因此您不必猜测(例如 sql profiler for microsoft sql server)。但是第一次查询的延迟可能与数据库无关,它只是 EF 内部初始化。 EF 是出了名的懒惰。

【讨论】:

    猜你喜欢
    • 2023-03-29
    • 2016-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-19
    • 1970-01-01
    • 2012-04-20
    • 1970-01-01
    相关资源
    最近更新 更多