【问题标题】:Entity framework, when call ToList() it will load FK objects automatically?实体框架,调用 ToList() 时会自动加载 FK 对象吗?
【发布时间】:2012-01-19 20:17:33
【问题描述】:

我对延迟加载的工作原理有点困惑。

例如,如果我有供应商对象,它具有地址外部对象作为属性,如下所示:

public class Supplier
{
        public int ID { get; set; }
        [Required]
        public string FullName { get; set; }
        public string TaxNumber { get; set; }
        public virtual Address DeliveryAddress { get; set; }
}

当我在以下位置设置断点时:

var suppliers = dbContext.Supplier.ToList();

我可以看到,地址信息对 var 供应商等可用。当我扩展 DeliveryAddress 属性时,它是可用的,这是否意味着所有 FK 对象都已加载?但另一方面,对于右侧的查询,我可以在断点处从 Visual Studio 中查看,是这样的:

{SELECT 
[Extent1].[ID] AS [ID], 
[Extent1].[FullName] AS [FullName], 
[Extent1].[TaxNumber] AS [TaxNumber], 
[Extent1].[DeliveryAddress_ID] AS [DeliveryAddress_ID]
FROM [dbo].[Suppliers] AS [Extent1]}

这意味着查询本身根本不会加载 Address 对象?

那么谁在加载 FK 对象? ToList() 还是 VS 调试器?

关于如何确认是否延迟加载的其他建议?

注意:所以现在我通过两个 ToList 调用确认延迟加载正在工作,一个设置延迟加载关闭,另一个设置延迟加载打开。有人可以指出一种方法来了解何时为 FK 属性发送另一个查询的延迟加载?

【问题讨论】:

  • 你如何确定 DeliveryAddress 已经被急切/非延迟加载?您确定只有 1 个查询发送到数据库吗?您可以启动 SQL Profiler 以准确查看发送到数据库的查询。
  • 嗨,我如何启动 SQL Profiler?我使用的是 SQL Server 2008 R2,似乎没有可用的 SQL Profiler 菜单。我只能看到:导入和导出、Server Management Studio、配置工具、集成服务?

标签: entity-framework-4 lazy-loading poco


【解决方案1】:

VS 调试器加载相关对象,它发生在第二个 SQL 查询中,而不是您在问题中显示的那个。当您在调试器中钻取地址对象时,调试器会访问对象的属性以显示它们的值。访问此对象会触发延迟加载和第二个 SQL 查询。

编辑

之所以有效,是因为父对象不是您的 Supplier 类型,而是派生自 Supplier 的类(“代理”)。这个派生类是在运行时动态创建的,并且有一些神秘的自动生成名称(你应该在调试器中看到这个类名)。这个动态类与你的基础Supplier 具有相同的属性,但它重载了DeliveryAddress 属性。 (这就是为什么那些导航属性必须是virtual 的原因,否则将无法重载。)查询使用已通过您的供应商查询获取的 FK 列值并通过该值检索地址。

当您或调试器使用supplier.DeliveryAddress 访问属性时调用的重载DeliveryAddress 属性的新getter 包含在运行时生成的代码,该代码运行SQL 查询以从数据库加载相关对象。派生的代理类包含各种额外的内部成员,尤其是对上下文/数据库连接的引用(以便能够运行查询)和一个标志,该标志指示代理对象它已经加载了导航属性,以便当您第二次访问 DeliveryAddress 时,它不会运行第二次冗余查询。

简而言之,这就是使用 POCO 进行延迟加载的工作方式。

【讨论】:

  • @Salauma,感谢您的额外解释,原始答案本身很好,但很明显。您能否建议一种方法来找出何时为 DeliveryAddress 属性发送查询? SQL Profiler 的问题似乎是我需要先安装它。
  • @pstar:在点击VS调试器对象树中的+节点钻取供应商收货地址的那一刻发送查询。发送的查询类似于:SELECT * FROM AdressTable WHERE AddressId = DeliveryAddress_ID.
  • @Salauma,我想看到的是对 FK Objects fire in action 的查询。我希望 DeliveryAddress 的查询不会触发,除非访问 FK 属性,但无法确认。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-20
相关资源
最近更新 更多