实体框架,当调用ToList()时会自动加载FK对象吗?

时间:2012-01-19 20:17:33

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

我对Lazy加载工作的方式感到困惑。

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

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调试器?

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

注意:现在我确认Lazy加载正在通过两个ToList调用,一个设置Lazy加载,另一个设置延迟加载。有人可以指点我知道什么时候延迟加载另一个查询是为FK属性发送的吗?

1 个答案:

答案 0 :(得分:6)

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

修改

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

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

这就是POCO延迟加载的方式。