实体框架Eager and Lazy加载

时间:2016-02-19 12:42:39

标签: c# entity-framework entity-framework-6 lazy-loading eager-loading

试图找出实体frameowrk中的Lazy和Eager加载之间的区别。说我有以下型号:

public interface IBaseEntityObject 
{
    public int Id {get; set;}
}


public abstract class BaseEntityObject : IBaseEntityObject
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id {get; set;}
}


public class Folder : BaseEntityObject
{   
    [DataMember]
    public string Name {get; set;}

    [DataMember]
    public virtual List<Letter> Letters {get; set;} 
}


public abstract class Letter : BaseEntityObject
{   
    [DataMember]
    public string Title {get; set;}

    [DataMember]
    public string Content {get; set;}

    public virtual Folder Folder {get; set;}

    [DataMember]
    public int FolderId {get; set;}

    [DataMember]
    public DateTime CreationDate {get; set;}
}

public class OutgoingLetter : Letter
{
    // .. OutgoingLetter properties
}

public class ReceviedLetter : Letter
{
    // .. ReceviedLetter properties
}


public class MyDbContext : DbContext
{
    public DbSet<Folder> Folders {get; set;}

    public DbSet<Letter> Letters {get; set;}


    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        // Folder <-> Letters       
        modelBuilder.Entity<Letter>()
        .HasRequired(t => t.Folder)
        .WithMany(f => f.Letters)
        .HasForeignKey(t => t.FolderId)
        .WillCascadeOnDelete(true);
    }
}

每当我从数据库中询问一个文件夹时,其主要目的是访问其中的信件。因此,如果我从一开始就加载它而不是在开始时再进行另一个数据库调用,那将是最好的吗?访问Letters属性我是否正确?

我已经读过,通过将EnableLazyLoading属性设置为false并从字母列表中删除虚拟关键字,可以通过在ctor中配置来禁用Lazy加载。

如果我只是在请求文件夹并保持启用延迟加载时使用Include(x =&gt; x.Lettters)会有什么区别?启用延迟加载时无法使用包含?

此外,在Letter模型中保存的Folder属性与延迟加载之间是否存在任何关系?在要求写信时我没有使用文件夹,但是我所看到的大多数模特在一对多的关系中包含了父属,我不明白为什么。

谢谢!

3 个答案:

答案 0 :(得分:3)

  

每当我从数据库中询问一个文件夹时,它的主要目的是访问其中的字母..因此,如果我从头开始加载它而不是在访问Letters属性时再调用另一个数据库,那么它是否最好?我是对的吗?

是的,没错。

  

我已经读过,通过将EnableLazyLoading属性设置为false并从字母列表中删除虚拟关键字,可以通过在ctor中配置来禁用Lazy加载。

如果您从不希望延迟加载某个属性,请删除virtual关键字。如果您有时需要它,有时则不需要,请在代码中创建新上下文时禁用延迟加载。

  

如果我只是在请求文件夹并保持启用延迟加载时使用Include(x =&gt; x.Lettters)会有什么区别?启用延迟加载时无法使用包含?

它们对彼此没有影响。如果你不包含这些字母,并且你试图访问该属性,EF将再次调用db来获取它们(延迟加载),如果你包含它们,它们是可用的,并且不会对数据库进行额外的调用。

  

此外,在Letter模型中保存的Folder属性与延迟加载之间是否存在任何关系?我在询问信件时不使用文件夹,但我见过的大多数模型都包含一对多关系中的父属性,我不明白为什么。

在大多数示例中,导航属性是以两种方式定义的,但如果您从不需要从字母中获取文件夹,那么在字母模型中定义该属性是完全合理的。

答案 1 :(得分:1)

  

我已经读过禁用Lazy加载是通过配置来完成的   通过将EnableLazyLoading属性设置为false来设置ctor   从字母列表中删除虚拟关键字

BOth并不聪明。这相当于将电池从汽车中取出来关闭发动机。

延迟加载ENABLED并不意味着它被使用,与虚拟

相同
  

如果我只使用Include(x =&gt; x.Lettters)会有什么区别   每当我要求一个文件夹并保持启用延迟加载?

后者可能会使用延迟加载(你在破坏之后不能使用)。

  

启用延迟加载时无法使用包含?

说谁?它可以完全 - 在这种情况下,延迟加载将不会发生已经包含的元素,这使您可以根据具体情况自由选择延迟加载。

答案 2 :(得分:0)

您也可以在启用延迟加载的情况下使用Include。不使用Include使代码更清晰,所以通常我只在我遇到性能问题的地方使用Include 此外,导航可能会在项目生命周期中发生变化,因此在懒惰负载下您无需记住它 此外,您不能在序列化期间使用延迟加载,否则您可能会序列化所有数据库。

仅供参考,Include也经常会产生非常难看的查询(但我从未遇到过性能问题)。

关于父级属性仅用于导航目的(即您可以从Letter转换为文件夹然后导航到文件夹的字母)。