试图找出实体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属性与延迟加载之间是否存在任何关系?在要求写信时我没有使用文件夹,但是我所看到的大多数模特在一对多的关系中包含了父属,我不明白为什么。
谢谢!
答案 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转换为文件夹然后导航到文件夹的字母)。