延迟加载(lazy  load)也成为懒加载,基本用于ORM中数据对象的一种默认加载方式,简单点讲延迟加载机制是为了避免无所谓的性能开销而提出来的,所谓延迟加载就是当真正需要数据的时候,才真正的执行数据加载操作。可以简单的理解为,只有使用的时候,才会实例化对象。

最大的有点就是能够大大的提高系统的性能。

通过一个案例来讲解,举一个很大众的应用场景,在大多的B2C应用中会设计到到用户开店的情况,这样我们就设计一个会员表,一个店铺表,当然一个会员可以开很多歌店铺,也就是说这里面一对多的映射。

看一下类图:

两个实体类,聚合关系,下面看一下第一种代码结构:

using System;using System.Collections.Generic;namespace LazyLoadShop{class Program    {static void Main(string[] args)        {            Users user = new Users("wu", "11");            Console.WriteLine("该用户所拥有的店铺有:");

            Console.ReadKey();foreach (Shop shop in user.myShops)            {                Console.WriteLine(shop.ShopName);            }            Console.Read();        }    }public class Users    {public int UserID { get; set; }public string UserName {  get; set; }public string PassWrod {  get; set; }public List<Shop> myShops { get; set; }public Users(string _name, string _passWrod)        {this.UserName = _name;this.PassWrod = "11"; //根据用户名从数据库提取密码            this.UserID = 123;            Console.WriteLine("大家好,我是" + _name);

if (this.PassWrod.Equals(_passWrod))            {///根据_UserID获取商户相信信息。赋值                myShops = new List<Shop>();                myShops.Add(new Shop(this.UserID));            }

        }

    }

public class Shop    {public Shop(int _UserID)        {this.ShopID = 1;this.UserID = _UserID;this.ShopUrl = "www.ss.com";this.ShopName = "超人店铺";                  }public int ShopID { get;set; }public int UserID { get;set; }public string ShopName { get; set; }public string ShopUrl  { get; set; }

    }

}

看一下运行结果:

这种结构应对一般的需求是没问题的,看一下上面的代码,可以看到,店铺(Shop)类是在用户(User)的构造函数中实现的实例化,也就是说我们在实例化用户(User)的时候,我们的店铺(Shop)类同样被实例化,当然,在这种应用场景下是没问题,但是假如应用场景变化了呢,一个用户对应N个店铺,也就是说,在我操作User的时候同样也在携带者店铺(Shop)这个类,显然这种方式会对性能有所损耗,尤其当我们只需要用户(User)不需要店铺(Shop)的时候,这简直就是一种内存浪费,我们想要达到的效果是:我们需要什么对象你给我实例化什么

根据这个需求,我们更改一下代码结构,我们只需要更改下用户类(User),第二版:

    public class Users    {public int UserID { get; set; }public string UserName { get; set; }public string PassWrod { get; set; }private List<Shop> myshops;public List<Shop> myShops        {get            {if (myshops != null)return myshops;else                {///根据_UserID获取商户相信信息。赋值                    myshops = new List<Shop>();                    myShops.Add(new Shop(this.UserID));return myshops;                };

            }

        }public Users(string _name, string _passWrod)        {this.UserName = _name;this.PassWrod = "11"; //根据用户名从数据库提取密码            this.UserID = 123;            Console.WriteLine("大家好,我是" + _name);          

        }

    }

我们在User类中公开了List<Shop>通过判断是否为空,而延迟实例化到店铺类(Shop)中,运行结果通第一版,其实延迟加载在ORM中很多成熟的框架已经采用这种思路,当然在.net中不能落伍的,在.net 4.0中微软已经为我们提供了专门用于延迟加载的类库Lazy<>类,我们看一下通过该类我们怎样实现店铺(Shop)类的延迟加载。

同样我们还是只需要更改用户类(User),第三版代码:

   public class Users    {public int UserID { get; set; }public string UserName { get; set; }public string PassWrod { get; set; }private readonly Lazy<List<Shop>> myshops;public List<Shop> myShops        {get            {                myshops.Value.Add(new Shop(this.UserID));return myshops.Value;            }

        }public Users(string _name, string _passWrod)        {this.UserName = _name;this.PassWrod = "11"; //根据用户名从数据库提取密码            this.UserID = 123;            Console.WriteLine("大家好,我是" + _name);            myshops = new Lazy<List<Shop>>                (                () =>(new List<Shop>())                              );        }    }

运行结果同上,这里需要注意点就是虽然我们在User中构造函数实现了Lazy<List<Shop>>类的实例,但是List<Shop>是未被实例化的,我们需要在Lazy的构造函数中指定他的回调函数。

还需注意的是上面的更改我们应用到了单例模式来实现List<Shop>是唯一的。

看以看出,Lazy<T>的引入使我们大大的简便了我们延迟初始化。

上传下源码

ORM内核原理解析之:延迟加载相关推荐

  1. Qt QComboBox内核原理解析

    关于QComboBox内核是如何实现的,原理是如何的,分析如下: QComboBox是继承自QWidget重写的窗口,的111区是用QLineEdit实现的,源码如下: QLineEdit *line ...

  2. mybatis延迟加载原理解析

    延迟加载前言: 在很多真实的实战的业务场景中,由于业务的复杂度,都会让我们进行过多的进行一些连接查询,在数据量少的时候,我们或许感受不到查询给我们带来的效率影响,在数据量和业务复杂的时候我们进行过多的 ...

  3. 2021年大数据Spark(二十二):内核原理

    目录 Spark内核原理 RDD 依赖 窄依赖(Narrow Dependency) ​​​​​​​Shuffle 依赖(宽依赖 Wide Dependency) ​​​​​​​如何区分宽窄依赖 ​​ ...

  4. 一篇不一样的docker原理解析 提高篇

    在上一篇 一篇不一样的docker原理解析 - uncle creepy的文章 - 知乎专栏 中,主要讨论了容器和虚拟机的区别,在实现细节上并没有深入,只是点到即止,在这篇提高篇中,将详细讨论容器的实 ...

  5. SparkSQL 之 Shuffle Join 内核原理及应用深度剖析-Spark商业源码实战

    本套技术专栏是作者(秦凯新)平时工作的总结和升华,通过从真实商业环境抽取案例进行总结和分享,并给出商业应用的调优建议和集群环境容量规划等内容,请持续关注本套博客.版权声明:禁止转载,欢迎学习.QQ邮箱 ...

  6. linux内核深度解析_十年磨一剑,第一本龙芯平台的Linux内核书来了

    <用"芯"探核:基于龙芯的Linux内核探索解析>是一本基于龙芯平台,结合源代码来探索和解析Linux-5.x内核的书. 市面上解析Linux 内核的经典书籍已有不少, ...

  7. 实验楼 linux内核原理与分析,《Linux内核原理与分析》第一周作业 20189210

    实验一 Linux系统简介 这一节主要学习了Linux的历史,Linux有关的重要人物以及学习Linux的方法,Linux和Windows的区别.其中学到了LInux中的应用程序大都为开源自由的软件, ...

  8. [转载] kprobe原理解析(一)

    From: https://www.cnblogs.com/honpey/p/4575928.html kprobe原理解析(一) kprobe是linux内核的一个重要特性,是一个轻量级的内核调试工 ...

  9. Merkle Tree(默克尔树)原理解析

    Merkle Tree(默克尔树)原理解析 一.Merkle Tree 1.1 Merkle Tree的特点 二.Hash list 三.Merkle tree VS Hash list 四.Merk ...

最新文章

  1. SQL Server 2005自带的Service Broker功能
  2. 与善淘网一起做慈善商店
  3. life at University of Liverpool
  4. zabbix (二)安装
  5. 再谈如何写好技术文档?
  6. SSM实现会议室预约管理系统
  7. 大数据网站汇总(数据搜集、大数据竞赛、)
  8. 区块链(二)-形象的理解区块链和中心化的技术差异
  9. js QQ音乐歌词显示在浏览器标题
  10. 1个钟是多久_一个时辰是多久,一个时辰是几个小时?
  11. 美团3年阿里4年,我的坎坷进阶之路
  12. TRS的WCM历史漏洞
  13. 从营销的角度看宜家成功的秘诀
  14. vue文本框中禁止输入空格和使用enter键
  15. 瑞芯微rk356x板子快速上手
  16. 一文尽揽2018谷歌I/O大会:AI很酷 Android P拯救睡前玩手机综合症
  17. linux下使用tar命令解压.tar.gz文件是参数的说明
  18. android查看内存使用情况
  19. Bmob小程序模板消息
  20. 回顾Bob大叔的简洁架构

热门文章

  1. mvc源码解读(10)-ParameterDescriptor方法Action方法的参数描述对象
  2. 注解的力量 -----Spring 2.5 JPA hibernate 使用方法的点滴整理(四):使用 命名空间 简化配置...
  3. Struts2中我所遇到的内存溢出(java.lang.OutOfMemoryError)异常错误介绍
  4. js中判断对象数据类型的方法
  5. android 自定义 打包文件类型,Android Studio配置打包生成自定义文件名
  6. java reader 方法_Java Reader reset()方法
  7. MySQL 函数 —— GROUP_CONCAT
  8. ABAP和Java单例模式的攻防
  9. 阿里巴巴获评《福布斯》全球最有投资价值公司
  10. OSGL 工具库 - 类型转换的艺术