zoukankan      html  css  js  c++  java
  • ORM内核原理解析之:延迟加载

       延迟加载(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>的引入使我们大大的简便了我们延迟初始化。

    上传下源码

  • 相关阅读:
    android常用的Application类
    Android一些问题的解决方案
    MakeFile相关
    Android源码与设计模式之notifyDataSetChanged()方法与观察者模式
    Activity启动模式与onNewIntent()简述
    (转)eval与迭代
    ADB命令
    其他常用工具类
    文件操作常用工具方法
    [TJOI2007] 可爱的质数
  • 原文地址:https://www.cnblogs.com/zhijianliutang/p/2353378.html
Copyright © 2011-2022 走看看