Eager, Lazy和显式加载在EF6中

23 浏览
0 Comments

Eager, Lazy和显式加载在EF6中

我阅读了这篇教程和这篇文章,但我不明白每种加载类型的具体用途。

我解释一下

我有这个 POCO:

public partial class dpc_gestion
{
    public dpc_gestion()
    {
        this.ass_reunion_participant = new HashSet();
        this.dpc_participant = new HashSet();
        this.dpc_reunion = new HashSet();
    }
    public int dpc_id_pk { get; set; }
    public Nullable dpc_id_gdp_fk { get; set; }
    public Nullable dpc_id_theme { get; set; }
    public int dpc_id_animateur_fk { get; set; }
    public Nullable dpc_date_creation { get; set; }
    public Nullable dpc_date_fin { get; set; }
    public Nullable dpc_date_engag_anim { get; set; }
    public Nullable dpc_flg_let_engag_anim { get; set; }
    public Nullable dpc_flg_fsoins_anim { get; set; }
    public virtual ICollection 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 { get; set; }
    public virtual ICollection 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. 是否存在这样的情况,即及早加载或显式加载在性能和响应速度方面比延迟加载更好?

谢谢

admin 更改状态以发布 2023年5月24日
0
0 Comments

问题1和2:

你对惰性加载急切加载的解释是正确的。
显式加载的使用与你描述的有点不同。

EntityFramework返回IQueryable对象,这些对象本质上包含对数据库的查询。但是这些对象直到第一次枚举它们时才被执行。
Load执行查询以便将其结果存储在本地。
调用Load相当于调用ToList并丢弃该List,而没有创建List的开销。

问题3:

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

问题4:

在断开连接的情况下(例如网络应用程序),您无法使用惰性加载,因为这些对象被转换为DTO,然后无法被EntityFramework跟踪。

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

0
0 Comments

如果这份简历是真的?

是的。

如果是真的,那么急切加载和显式加载有什么区别?

急切加载懒惰加载 的相反,但显式加载类似于懒惰加载唯一的不同是:您需要在代码中显式检索关联的数据;当您访问导航属性时,它不会自动发生。您可以通过获取实体的对象状态管理器条目,并为集合调用Collection.Load方法或为保存单个实体的属性调用Reference.Load方法来手动加载相关数据。

来自techblog

急切加载:

急切加载是懒惰加载的相反,即以特定查询请求的对象为中心,加载一组相关对象。

显式加载:

当查询返回对象时,相关对象并不会同时加载。默认情况下,它们不会加载,直到使用导航属性上的Load方法显式请求。

并且:

如果我使用懒惰加载,例如调用dpc_gestion.dpc_participant,是否将导航属性加载?还是会出现异常?

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

在性能和响应方面,急切加载或显式加载何时比懒惰加载更好?

急切加载通常对于需要检索主表的所有检索行的相关数据时更有效。当关系不太多时,急切加载是减少服务器上进一步查询的良好方法。但是当您知道您不会立即需要属性时,懒惰加载可能是一个不错的选择。并且,当处置您的数据库上下文后,急切加载是一个解决懒惰加载无法进行的情况的好选择。例如,考虑以下情况:

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

调用此方法后,您无法懒惰加载相关实体,因为db已被处置,因此在这里使用急切加载更好。

还有一件事要注意的是:懒惰加载将生成多个SQL请求,而急切加载将使用一个请求加载数据。这也是解决ORM中的n+1查询问题的一个好选择。

请查看此帖子:什么是关于n+1查询问题?

0