延迟加载
延迟加载是延迟相关数据的加载,直到您特别请求它。它与立即加载相反。例如,Student实体包含StudentAddress实体。在延迟加载中,上下文首先从数据库加载Student实体数据,然后当我们访问StudentAddress属性时,它将加载StudentAddress实体,如下所示。
实体类:
public class Student
{
public int StudentID { get; set; }
public string StudentName { get; set; }
public Nullable<int> StandardId { get; set; }
public byte[] RowVersion { get; set; }
public virtual Standard Standard { get; set; }
public virtual StudentAddress StudentAddress { get; set; } //在EntityFramework中被标记为virtual的导航属性的数据在查询的时候默认是不会被查询的,只有当使用到该属性的时候才会去数据库查询,默认是延迟加载的
public virtual ICollection<Course> Courses { get; set; }
}
public class Standard
{
public int StandardId { get; set; }
public string StandardName { get; set; }
public string Description { get; set; }
public virtual ICollection<Student> Students { get; set; }
public virtual ICollection<Teacher> Teachers { get; set; }
}
using (var ctx = new SchoolDBEntities())
{
//只加载Student数据
IList<Student> studList = ctx.Students.ToList<Student>();
Student std = studList[0];
//当使用到Student中的StudentAddress属性时才会去数据库查询StudentAddress的数据(单独的SQL查询)
StudentAddress add = std.StudentAddress;
}
上面显示的代码将导致两个SQL查询。首先,它将获取所有的学生:
SELECT
[Extent1].[StudentID] AS [StudentID],
[Extent1].[StudentName] AS [StudentName],
[Extent1].[StandardId] AS [StandardId]FROM [dbo].[Student] AS [Extent1]
然后,当我们需要用到StudentAddress的数据时,它会发送以下查询:
exec sp_executesql N'SELECT
[Extent1].[StudentID] AS [StudentID],
[Extent1].[Address1] AS [Address1],
[Extent1].[Address2] AS [Address2],
[Extent1].[City] AS [City],
[Extent1].[State] AS [State]
FROM [dbo].[StudentAddress] AS [Extent1]
WHERE [Extent1].[StudentID] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=1
禁用延迟加载
我们可以禁用特定实体或上下文的延迟加载。若要关闭特定属性的延迟加载,请不要将其设置为virtual。要关闭上下文中所有实体的延迟加载,请将其configuration属性设置为false。
关闭某个实体中的导航属性延迟加载:
public class Student
{
public int StudentID { get; set; }
public string StudentName { get; set; }
public Nullable<int> StandardId { get; set; }
public byte[] RowVersion { get; set; }
public StudentAddress StudentAddress { get; set; } //在EntityFramework中没有标记为virtual的导航属性的数据在查询的时候会自动进行关联加载
public virtual ICollection<Course> Courses { get; set; }
}
全局禁用延迟加载(不建议影响性能):
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Core.Objects;
using System.Linq;
public partial class SchoolDBEntities : DbContext
{
public SchoolDBEntities(): base("name=SchoolDBEntities")
{
this.Configuration.LazyLoadingEnabled = false;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
}
}
延迟加载规则:
1、context.Configuration.ProxyCreationEnabled应该为true。
2、context.Configuration.LazyLoadingEnabled应该是true。
3、导航属性应该定义为public, virtual。如果属性未定义为virtual, Context将不会进行延迟加载,而是默认立即加载。
参考
https://www.entityframeworktutorial.net/
https://msdn.microsoft.com/