我已阅读此tutorial和此article,但我并不完全了解每种加载类型的使用情况。
我解释
我有这个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; }
}
我理解这一点:
对于延迟加载:因为加载是懒惰的,如果我调用dbset dpc_gestion
,则会加载所有导航属性赢了 。这种类型的负载是性能和响应性最好的。它默认启用,如果我想重新启用它,我必须设置:
context.Configuration.ProxyCreationEnabled = true;
context.Configuration.LazyLoadingEnabled = true;
急切加载
它不是懒惰的:它在我加载dpc_gestion
时加载了所有导航属性。可以使用include
方法加载导航属性。要启用此加载类型:
context.Configuration.LazyLoadingEnabled = false;
用于显式加载
这就像热切加载一样,但我们使用Load
方法代替include
。
所以我想知道:
dpc_gestion.dpc_participant
,导航属性是否会加载?或者我会收到异常?由于
答案 0 :(得分:18)
如果这个小简历是真的吗?
是
如果是真的,那么热切和显式加载有什么区别?
急切加载与延迟加载相反,但显式加载类似于延迟加载,除了:您在代码中显式检索相关数据;访问导航属性时不会自动执行此操作。您可以通过获取实体的对象状态管理器条目并为集合调用Collection.Load
方法或为包含单个实体的属性调用Reference.Load
方法来手动加载相关数据。
来自techblog:
渴望加载:
急切加载是 延迟加载的反面,即:进程 加载一组特定的相关对象以及对象 在查询中明确请求的内容。
明确加载:
显式加载定义为:查询返回对象时, 相关对象不会同时加载。默认情况下,它们是 直到在使用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选择问题的不错选择。 看看这篇文章:What is the n+1 selects issue?
答案 1 :(得分:6)
问题1和2:
您对延迟加载和急切加载的解释是正确的。
使用显式加载与您描述的有点不同。
EntityFramework
返回IQueryable
个对象,这些对象基本上包含对数据库的查询。但这些只有在第一次被枚举时才会执行
Load
执行查询,以便将结果存储在本地
调用Load
与调用ToList
并丢弃List
相同,而无需创建List
的开销。
问题3:
如果您使用延迟加载,EntityFramework
将负责为您加载导航属性,因此您不会获得例外。
请注意,这可能需要一段时间才能使应用无响应。
问题4:
在断开连接的情况下(例如网络应用程序),您无法使用延迟加载,因为这些对象会被转换为DTO,然后不会被{{1 }}
此外,如果您知道自己将使用导航属性,那么将其加载急切是一种很好的做法,因此您不会等到从数据库加载它们 例如,假设您将结果存储在列表中并将其绑定到WPF DataGrid。如果DataGrid访问尚未加载的属性,则在显示该属性之前,用户会遇到明显的超时。此外,应用程序在加载期间不会响应(如果您没有异步加载)。
答案 2 :(得分:1)
在这里,您将学习如何在实体图中显式加载相关实体。 显式加载在EF 6和EF Core中均有效。
即使禁用了延迟加载(在EF 6中),仍然可以延迟加载相关的实体,但是必须通过显式调用来完成。使用Load()
方法显式加载相关实体。请考虑以下示例。
using (var context = new SchoolContext())
{
var student = context.Students
.Where(s => s.FirstName == "Bill")
.FirstOrDefault<Student>();
context.Entry(student).Reference(s => s.StudentAddress).Load();
// loads StudentAddress
context.Entry(student).Collection(s => s.StudentCourses).Load();
// loads Courses collection
}
在上面的示例中,context.Entry(student).Reference(s => s.StudentAddress).Load()
加载StudentAddress
实体。 Reference()
方法用于获取具有指定参考导航属性的对象,而Load()
方法则显式加载该对象。
以同样的方式,context.Entry(student).Collection(s => s.Courses).Load()
加载学生实体的集合导航属性Courses。 Collection()
方法获取一个表示集合导航属性的对象。
Load()
方法在数据库中执行SQL查询以获取数据并在内存中填充指定的引用或收集属性,如下所示。
Query():
您还可以编写LINQ-to-Entities查询以在加载之前过滤相关数据。 Query()方法使我们能够为相关实体编写进一步的LINQ查询,以过滤出相关数据。
using (var context = new SchoolContext())
{
var student = context.Students
.Where(s => s.FirstName == "Bill")
.FirstOrDefault<Student>();
context.Entry(student)
.Collection(s => s.StudentCourses)
.Query()
.Where(sc => sc.CourseName == "Maths")
.FirstOrDefault();
}
在上面的示例中,.Collection(s => s.StudentCourses).Query()
允许我们为StudentCourses
实体编写进一步的查询。