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

上传下源码

原文地址:https://www.cnblogs.com/zhijianliutang/p/2353378.html