zoukankan      html  css  js  c++  java
  • EF三种加载方法

    EF性能之关联加载

     

    鱼和熊掌不能兼得

    ——中国谚语

    一、介绍

     Entity Framework作为一个优秀的ORM框架,它使得操作数据库就像操作内存中的数据一样,但是这种抽象是有性能代价的,故鱼和熊掌不能兼得。但是,通过对EF的学习,可以避免不必要的性能损失。本篇只介绍关联实体的加载的相关知识,这在我之前的文章中都有介绍。

    我们已经了解到EF的关联实体加载有三种方式:Lazy Loading,Eager Loading,Explicit Loading,其中Lazy LoadingExplicit Loading都是延迟加载。

    (一)Lazy Loading使用的是动态代理,默认情况下,如果POCO类满足以下两个条件,EF就使用Lazy Loading:

    1. POCO类是Public且不为Sealed。
    2. 导航属性标记为Virtual。

    关闭Lazy Loading,可以将LazyLoadingEnabled设为false,如果导航属性没有标记为virtual,Lazy Loading也是不起作用的。

    (二)Eager Loading使用Include方法关联预先加载的实体。

    (三)Explicit Loading使用Entry方法,对于集合使用Collection,单个实体则使用Reference。

    二、实例

    下面通过实例来理解这几种加载方式。

    有下面三个实体:Province,City,Governor,一个Province有多个City,并且只有一个Governor。

       1:      public class Province
       2:      {
       3:          public int Id { get; set; }
       4:          public string Name { get; set; }
       5:   
       6:          public virtual Governor Governor { get; set; }
       7:   
       8:          public virtual List<City> Cities { get; set; }
       9:      }
      10:   
      11:      public class City
      12:      {
      13:          public int Id { get; set; }
      14:          public string Name { get; set; }
      15:      }
      16:   
      17:   
      18:      public class Governor
      19:      {
      20:          public int Id { get; set; }
      21:          public string Name { get; set; }
      22:      }

    Lazy Loading

       1:          private static void LazyLoading(EFLoadingContext ctx)
       2:          {
       3:              //发送一条查询到数据库,查询所有的province
       4:              var list = ctx.Provines.ToList();
       5:              foreach (var province in list)
       6:              {
       7:                  //每次遍历(用到导航属性时)都发送2条查询,一条查询当前province包含的city和另一条查询当前province的governor
       8:                  //如果ctx.Configuration.LazyLoadingEnabled为false或者前者为true,但是导航属性没有标注为virtual,下面的操作都会抛出异常
       9:                  Print(province);
      10:              }
      11:          }

    Eager Loading

       1:          private static void EagerLoading(EFLoadingContext ctx)
       2:          {
       3:              //发送一条查询到数据库库,查询所有的province并关联city和governor
       4:              var list = ctx.Provines.Include(t => t.Cities).Include(t => t.Governor);
       5:              foreach (var province in list)
       6:              {
       7:                  //不管ctx.Configuration.LazyLoadingEnabled为false,还是没有标注导航属性virtual,都不会抛出异常
       8:                  Print(province);
       9:              }
      10:          }

    Explicti Loading

       1:          private static void ExplicitLoading(EFLoadingContext ctx)
       2:          {
       3:              //发送一条查询到数据库,查询所有的province
       4:              var list = ctx.Provines.ToList();
       5:              foreach (var province in list)
       6:              {
       7:                  var p = ctx.Entry(province);
       8:                  //发送一条查询,查询所有当前province的city
       9:                  p.Collection(t => t.Cities).Load();
      10:                  //发送一条查询,查询当前province的governor
      11:                  p.Reference(t => t.Governor).Load();
      12:                  //不管ctx.Configuration.LazyLoadingEnabled为false,还是没有标注导航属性virtual,都不会抛出异常
      13:                  Print(province);
      14:              }
      15:          }

    Print方法

       1:          private static void Print(Province province)
       2:          {
       3:              Console.WriteLine("省:【{0}】,市:【{1}】,省长:【{2}】", province.Name, string.Join(",", province.Cities.Select(t => t.Name)), province.Governor.Name);
       4:          }

    三、总结

    关于关联加载实体基本上就是这些内容吧,如果想看这部分详细的介绍,可以参考我这篇文章的后半部分。总的来说,这部分比较简单,一个LazyLoadingEnabled设置,三种加载方式。Lazy Loading会生成大量的sql,Eager Loading生成的关联查询比较负责,Explicit Loading同Lazy Loading一样生成很多的sql,但是有一些其他优点,比如:导航属性可以不用标注为virtual。如果这几种关联都不能解决实际问题,可以直接使用sql查询。

  • 相关阅读:
    智慧养老民政监管平台建设方案
    CF600E Lomsat gelral dsu on tree
    dsu on tree详解
    【Spring 从0开始】Spring5 新功能,整合日志框架 Log4j2
    【Spring 从0开始】JdbcTemplate 数据库事务管理
    【Spring 从0开始】JdbcTemplate 数据库事务参数
    【Spring 从0开始】JdbcTemplate 数据库事务管理
    【Spring 从0开始】JdbcTemplate 操作数据库
    【Spring 从0开始】AOP 操作
    【Spring 从0开始】AOP 操作中的相关术语、环境准备
  • 原文地址:https://www.cnblogs.com/liangxiaofeng/p/5809301.html
Copyright © 2011-2022 走看看