EF6基础系列(九)---预先加载、延迟加载、显示加载

1.预先加载:

预先加载:在对一种类型的实体进行查询时,将相关的实体作为查询的一部分一起加载。预先加载可以使用Include()方法实现。

1.加载一个相关实体类型

栗子:使用Include()方法从数据库中获取所有学生及成绩级别。
导航属性实现预先加载:

using (var ctx = new SchoolDBEntities())
{
  var stud1 = ctx.Students
          .Include("Standard")
          .Where(s => s.StudentName == "Bill")
          .FirstOrDefault<Student>();
}

lambda表达式实现预先加载:

using (var ctx = new SchoolDBEntities())
{
  var stud1 = ctx.Students.Include(s => s.Standard)
          .Where(s => s.StudentName == "Bill")
          .FirstOrDefault<Student>();
}

2.加载多个相关实体类型

栗子:使用Include()方法从数据库中获取所有学生及其成绩级别和评分老师。
导航属性实现预先加载:

using (var ctx = new SchoolDBEntities())
{
    var stud1 = ctx.Students.Include("Standard.Teachers")
                .Where(s => s.StudentName == "Bill")
             .FirstOrDefault<Student>();
}                

lambda表达式实现预先加载:

using (var ctx = new SchoolDBEntities())
{
  var stud1 = ctx.Students.Include(s => s.Standard.Teachers)
                .Where(s => s.StudentName == "Bill")
                .FirstOrDefault<Student>();
}

2.延迟加载

1.概念

延迟加载顾名思义就是不立即加载,而是在我们访问的时候才加载,这和预先加载刚好相反。
一个栗子:查询Student的StudentAddress

using (var ctx = new SchoolDBEntities())
{
    //这里只加载student实体
  IList<Student> studList = ctx.Students.ToList<Student>();
  Student std = studList[0];

  //只加载特定student的住址(通过一个单独的sql进行实现的)
  StudentAddress add = std.StudentAddress;
}

2.禁用延迟加载

我们可以禁用特定实体或者特定context的延迟加载。去掉实体导航属性的virtual,实体就不能进行延迟加载了。也可以通过context的cofiguration实现禁用该context下所有实体的延迟加载,代码如下:

public partial class SchoolDBEntities : DbContext
{
    public SchoolDBEntities(): base("name=SchoolDBEntities")
    {
        //SchoolDBEntities的所有实体都禁用延迟加载
    this.Configuration.LazyLoadingEnabled = false;
  }
  //如果去掉virtual那么Students禁用延迟加载
  public virtual DbSet<Student> Students { get; set; }
  protected override void OnModelCreating(DbModelBuilder modelBuilder){}
}

3.延迟加载前提

如果要实现延迟加载,必须满足下边三个条件,缺一不可

1.context.Configuration.ProxyCreationEnabled应为true。
2.context.Configuration.LazyLoadingEnabled应为true。
3.导航属性应定义为public virtual xxx,如果属性未定义为virtual,则Context不会进行延迟加载。

3.显示加载

1.Load方法

即使禁用了延迟加载(在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() Collection()加载student的集合导航属性Courses,Load()方法显示加载。

2.Query方法

有时候我们想对查询的结果在加载前进行过滤,Query()方法就可以排上用场了。
一个栗子:查询名字为bill的学生的课程集合中数学课。

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() 不加载结果集,我们可以把Query()方法的结果看作是一个中间结果,可以对中间结果做进一步过滤。

原文地址:https://www.cnblogs.com/wyy1234/p/9629502.html

时间: 2024-10-08 02:20:12

EF6基础系列(九)---预先加载、延迟加载、显示加载的相关文章

【C++自我精讲】基础系列五 隐式转换和显示转换

0 前言 1)C++的类型转换分为两种,一种为隐式转换,另一种为显式转换. 2)C++中应该尽量不要使用转换,尽量使用显式转换来代替隐式转换. 1 隐式转换 定义:隐式转换是系统跟据程序的需要而自动转换的. 1)C++类型(char,int,float,long,double等)的隐式转换: 算术表达式隐式转换顺序为: 1.char - int - long - double 2.float - double //1)算术表达式 int m = 10; double n = m;//n = 10

js 利用 ajax 加载 js ,显示加载进度 ,严格按照js的顺序先后加载到页面

js 利用 ajax 加载 js ,显示加载进度 ,严格按照js的顺序先后加载到页面 , 做手机端开发时,发现一个问题,有些浏览器,在网速比较慢的情况下,js文件没有加载完,后续的调用已经开始调用了,导致出错.后来使用此法,保证了任何时候都完全是按照js的先后顺序执行的. 源码: /** * js 利用 ajax 加载 js ,显示加载进度 ,严格按照js的顺序先后加载到页面 * 原理:利用 ajax 异步多线程快速加载, 每个文件加载完成后存入到加载完成数组中, * 显示到页面时完全按传入的顺

EF6基础系列(九)--- 附加离线实体图集到上下文

附加离线实体图集到上下文 这节主要内容是通过不同的方法将离线实体附加到上下文中. 在离线场景中,保存一个实体要略微困难一些.当我们保存一个离线的实体图集或一个单独的离线实体时,我们需要做两件事.首先,我们要把实体附加到新的上下文中,让上下文了知道存在这些实体.其次,我们需要手动设置每个实体的EntityState,因为新的上下文不知道这些离线实体都经过了些什么操作,所以新的上下文不能自动地给实体添加EntityState. 下图说明了此过程. 为了将离线实体附加到上下文,并为实体图中的每个实体设

EF6基础系列(十一)---EF6中的异步查询和异步保存

EF6中的异步查询和异步保存 在.NET4.5中介绍了异步操作,异步操作在EF中也很有用,在EF6中我们可以使用DbContext的实例进行异步查询和异步保存. 1.异步查询 下边是一个通过L2E语法实现异步查询的栗子: private static async Task<Student> GetStudent() { Student student = null; using (var context = new SchoolDBEntities()) { Console.WriteLine

EF6基础系列(12)--- EF进行批量添加/删除

EF6添加了批量添加/删除实体集合的方法,我们可以使用DbSet.AddRange()方法将实体集合添加到上下文,同时实体集合中的每一个实体的状态都标记为Added,在执行SaveChange()方法时为每个实体执行Insert操作:同样的我们使用DbSet.RemoveRange()方法将集合中的所有实体都标记为deleted状态,在执行SaveChange()方法时为每一条数据执行delete操作. 通过AddRange()和RemoveRange()方法可以有效提升性能,所以建议在进行不批

EF6基础系列(一)---什么是Entity Framework

什么是Entity Framework 1.EF的概念 在.NET3.5之前,我们经常编写ADO.NET代码或企业数据访问块来保存或检索底层数据库中的数据.做法是:打开过一个数据库的连接,创建一个DataSet来获取或提交数据到数据库,通过将DataSet中的数据和.NET对象相互转换来满足业务需求.这是一个麻烦且容易出错的过程.Microsoft提供了“Entity Framework”框架,用于自动地执行所有上述与数据库相关的活动.EF是一个适用于.NET开发的开源ORM框架.它使开发人员能

EF6基础系列(五)---EF中的实体关系

这一节将总结EF是怎么管理实体之间的关系.EF与数据库一样支持三种关系类型:①一对一 ,②一对多,③多对多. 下边是一个SchoolDB数据库的实体数据模型,图中包含所有的实体和各个实体间的关系.通过设计器我们很容易看出实体间的对应关系 1.一对一 如上图,Student和StudentAddress具有一对一的关系(零或一).一个学生只能有一个或零个地址.实体框架将Student实体导航属性添加到StudentAddress实体中,将StudentAddress实体导航属性添加到Student

EF6基础系列(十)---离线场景保存实体和实体图集

离线场景保存和删除实体/实体图集 这一节的内容是在离线场景中保存实体和实体图集 在离线场景中,当我们保存一个离线的实体图集或一个单独的离线实体时,我们需要做两件事.首先,我们要把实体附加到新的上下文中,让上下文了知道存在这些实体.其次,我们需要手动设置每个实体的EntityState,因为新的上下文不知道这些离线实体都经过了些什么操作,所以新的上下文不能自动地给实体添加EntityState.上一节我们清楚了附加离线图集的方法,附加离线图集时默认添加的EntityState不一定合适,所以我们就

动态链接库DLL的加载:隐式加载(载入时加载)和显式加载(运行时加载)

静态链接库在链接时,编译器会将 .obj 文件和 .LIB 文件组织成一个 .exe 文件,程序运行时,将全部数据加载到内存. 如果程序体积较大,功能较为复杂,那么加载到内存中的时间就会比较长,最直接的一个例子就是双击打开一个软件,要很久才能看到界面.这是静态链接库的一个弊端. 动态链接库有两种加载方式:隐式加载和显示加载. 隐式加载又叫载入时加载,指在主程序载入内存时搜索DLL,并将DLL载入内存.隐式加载也会有静态链接库的问题,如果程序稍大,加载时间就会过长,用户不能接受. 显式加载又叫运行