EF6中的热切、懒惰和显式加载

本文关键字:加载 EF6 | 更新日期: 2023-09-27 18:29:04

我已经阅读了本教程和本文,但我并不完全理解每种加载类型的用法。

我解释

我有这个POCO:

public partial class dpc_gestion
{
    public dpc_gestion()
    {
        this.ass_reunion_participant = new HashSet<ass_reunion_participant>();
        this.dpc_participant = new HashSet<dpc_participant>();
        this.dpc_reunion = new HashSet<dpc_reunion>();
    }
    public int dpc_id_pk { get; set; }
    public Nullable<int> dpc_id_gdp_fk { get; set; }
    public Nullable<int> dpc_id_theme { get; set; }
    public int dpc_id_animateur_fk { get; set; }
    public Nullable<System.DateTime> dpc_date_creation { get; set; }
    public Nullable<System.DateTime> dpc_date_fin { get; set; }
    public Nullable<System.DateTime> dpc_date_engag_anim { get; set; }
    public Nullable<bool> dpc_flg_let_engag_anim { get; set; }
    public Nullable<bool> dpc_flg_fsoins_anim { get; set; }
    public virtual ICollection<ass_reunion_participant> ass_reunion_participant { get; set; }
    public virtual theme_dpc theme_dpc { get; set; }
    public virtual gdp_groupe_de_pair gdp_groupe_de_pair { get; set; }
    public virtual ICollection<dpc_participant> dpc_participant { get; set; }
    public virtual ICollection<dpc_reunion> dpc_reunion { get; set; }
}

我理解这一点:

  1. 对于延迟加载:因为加载是延迟的,如果我调用dbset dpc_gestion,则不会加载所有导航属性。这种类型的负载在性能和响应性方面是最好的。它是默认启用的,如果我想重新启用它,我必须设置:

    context.Configuration.ProxyCreationEnabled = true;    
    context.Configuration.LazyLoadingEnabled = true;
    
  2. 对于急切的加载它并不懒惰:当我加载dpc_gestion时,它加载了所有导航属性。导航属性可以使用include方法加载。要启用此加载类型:

    context.Configuration.LazyLoadingEnabled = false;
    
  3. 对于显式加载这就像急切的加载,但我们使用Load方法而不是include

所以我想知道:

  1. 如果这个小简历是真的
  2. 如果这是真的,那么热切加载和明确加载之间有什么区别
  3. 如果我使用延迟加载并调用例如dpc_gestion.dpc_participant,导航属性会加载吗?否则我会得到一个例外
  4. 在性能和响应性方面,是否存在热切加载或显式加载优于懒惰加载的情况

感谢

EF6中的热切、懒惰和显式加载

如果这个小简历是真的?

是的。

如果这是真的,那么热切加载和明确加载之间有什么区别?

Eager loadingLazy loading反,但Explicit loading类似于Lazy loading,只是:显式检索代码中的相关数据;当您访问导航属性时,它不会自动发生。通过获取实体的对象状态管理器条目,并为集合调用Collection.Load方法,或为包含单个实体的属性调用Reference.Load方法,可以手动加载相关数据。

来自科技博客:

热切装载:

热切加载是懒惰加载的反面,懒惰加载是:与对象一起加载一组特定的相关对象在查询中明确请求的。

显式加载:

显式加载定义为:当查询返回对象时,不同时加载相关对象。默认情况下,它们是在使用上的Load方法显式请求之前未加载导航属性。

和:

如果我使用延迟加载,并且我调用例如dpc_gestion.dpc_participant,导航属性会加载吗?否则我会得到一个例外?

您不会得到任何异常,并且应该加载导航属性。

是否存在热切加载或显式加载更好的情况性能和响应能力方面的延迟加载?

当您需要主表中所有检索行的相关数据时,快速加载通常效率更高。而且,当关系不太大时,热切加载将是减少服务器上进一步查询的好做法。但是,当您知道您不会立即需要属性时,延迟加载可能是一个不错的选择。此外,在数据库上下文将被丢弃并且懒惰加载无法再发生的情况下,热切加载也是一个不错的选择。例如,考虑以下内容:

public List<Auction> GetAuctions()
{
    using (DataContext db = new DataContext())
    {
        return db.Auctions.ToList();
    }
}

调用此方法后,您无法延迟加载相关实体,因为db已被释放,因此Eager Loading将是更好的选择。

还有一点需要注意:懒惰加载将产生多个SQL请求,而急切加载切加载也是解决ORM中n+1选择问题的好选择。看看这篇文章:n+1选择问题是什么?

问题1和2:

您对懒惰加载渴望加载strong>显式加载的使用与您描述的有点不同。

EntityFramework返回IQueryable对象,这些对象实质上包含对数据库的查询。但是,直到第一次枚举它们时,才执行这些操作
CCD_ 13执行该查询,使得其结果被本地存储
调用Load与调用ToList并丢弃该List相同,而不具有创建List的开销。

问题3:

如果使用延迟加载,EntityFramework将负责为您加载导航属性,因此不会出现异常
请记住,这可能需要一段时间,并使您的应用程序没有响应

问题4:

在断开连接的情况下(例如网络应用程序),不能使用延迟加载,因为这些对象被转换为DTO,然后EntityFramework不会跟踪。

此外,如果您知道要使用导航属性,那么最好是急切地加载它,这样您就不必等到从数据库加载它们了
例如,假设您将结果存储在列表中,并将其绑定到WPF数据网格。如果DataGrid访问尚未加载的属性,则用户会经历明显的超时,直到该属性显示为止。此外,应用程序在加载期间不会做出响应(如果不是异步加载)。