实体框架 急于加载和延迟加载
本文关键字:加载 延迟加载 框架 于加载 实体 | 更新日期: 2023-09-27 18:35:25
试图找出实体框架中延迟加载和渴望加载之间的区别。假设我有以下型号:
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 属性时进行另一个数据库调用,那将是最好的,我是否正确?
我已经读到禁用延迟加载是通过在 ctor 中配置它来完成的,方法是将 EnableLazyLoading 属性设置为 false 并从字母列表中删除虚拟关键字。
如果我在请求文件夹并保持延迟加载启用时只使用 Include(x => x.Lettters),会有什么区别?启用延迟加载时不能使用包含?
此外,Letter 模型中保存的 Folder 属性与延迟加载之间是否存在任何关系?我在索要信件时不使用文件夹,但我见过的大多数模型都包含一对多关系中的父亲属性,我真的不明白为什么。
谢谢!
每当我从数据库中询问文件夹时,它的主要目的是访问其中的字母。因此,如果我从一开始就加载它而不是在访问 Letters 属性时进行另一个数据库调用,那将是最好的,我是否正确?
是的,正确。
我已经读到禁用延迟加载是通过在 ctor 中配置它来完成的,方法是将 EnableLazyLoading 属性设置为 false 并从字母列表中删除虚拟关键字。
如果您不希望延迟加载某个属性,请删除 virtual
关键字。如果有时需要它,有时不需要,请在代码中创建新上下文时禁用延迟加载。
如果我在请求文件夹并保持延迟加载启用时只使用 Include(x => x.Lettters),会有什么区别?启用延迟加载时不能使用包含?
它们对彼此没有影响。如果未包含字母,并且尝试访问该属性,EF 将再次调用 db 以获取它们(延迟加载),如果包含它们,则它们可用,并且不会对数据库进行额外调用。
此外,Letter 模型中保存的 Folder 属性与延迟加载之间是否存在任何关系?我在索要信件时不使用文件夹,但我见过的大多数模型都包含一对多关系中的父亲属性,我真的不明白为什么。
在大多数示例中,导航属性以两种方式定义,但如果永远不需要从信件中获取文件夹,则不在字母模型中定义该属性是完全有意义的。
我已经读到禁用延迟加载是通过在 通过将启用延迟加载属性设置为 false 和 从字母列表中删除虚拟关键字
博特不聪明。这相当于将电池从汽车中取出只是为了关闭发动机。
延迟加载启用并不意味着它被使用,与虚拟相同
如果我只使用 Include(x => x.Lettters) 会有什么区别 每当我要求一个文件夹并保持启用延迟加载时?
后者将能够使用延迟加载(破坏后你不能)。
启用延迟加载时不能使用包含?
谁说的?它完全可以 - 在这种情况下,对于已经包含的元素,延迟加载根本不会发生,这使您可以根据具体情况自由选择延迟加载或不延迟加载。
您也可以在启用延迟加载的情况下使用"包括"。不使用 Include 会使代码更清晰,因此通常我仅在遇到性能问题时才使用 Include。
此外,导航可能会在项目生命周期内发生变化,因此对于延迟加载,您无需记住它。
而且,您不能在序列化期间使用延迟加载,否则您可能会序列化所有数据库。
仅供参考,Include 也经常生成非常丑陋的查询(但我从未遇到过性能问题)。
关于父属性仅用于导航目的(即,您可以从信件导航到文件夹,然后导航到文件夹的字母)。