一起谈.NET技术,浅谈C#中的延迟加载(1)——善用委托

  很久以前就听过延迟加载这个东西,不过没有理解是什么意思,现在算是了解一二了,写点文章作为读书笔记,把自己的想法记录一下,希望对初学者帮助,不管是初学者或者高手如果发现文章那里写得不好或者有更好的思路和做法记得告诉我哦^^。文章打算写成两三篇,这个是第一篇。

  在三层结构中我们通常会使用多一个叫做模型层的东西,这一层中最主要做的事情是把数据库中的表 (或者其他数据源,例如xml或者自己定义的一种数据格式)转成对应的类,例如有一个文章表,这时候在这一层就会有一个文章类;文章类的属性对应着文章表的列,例如文章标题属性对应文章标题列。 实体类和数据表一一对应是最简单的情况,这时候实体类和实体类是各自独立存在的,没有出现相互引用的关系。 但是,几乎每一个数据库中的表都是存在关联关系的(关系型数据库),例如除了文章表之外,还会有一个文章分类表,假如说每一篇文章都必须属于一个分类,那么在数据库中表现出来的就是文章表中有一个外键字段指向文章分类表的主键 ,在C#代码中表示出来的是文章类中有一个属性(文章分类ID),通过这个属性我们就可以知道文章所属的分类、并且可以准确地通过代码查询数据库,获取一个文章分类实体类的对象,读取到文章所属分类的相关信息。

  以上的过程看起来一点问题都没有,整理一下思路,就是读取数据库,获取一个文章类对象,通过文字类对象中的文章分类ID的值,以这个值为查询条件去数据库中读取数据,获取一个文章分类对象,当然对数据库的操作我们通常 是封装在数据访问层中。然而从面向对象的角度考虑,我们会希望从文章类包含有文章分类的信息,用代码表示文章分类和文章两个实体类如下:

从上面的代码可以看到,在文章实体类中出现了一个Model.ArticleCategory类型的属性Category,我们想要的就是通过这个属性直接读取文章所属分类的详细信息。问题出现了,在数据库访问层中我们从数据库中读取数据去实例化一个文章实体类对象之后, 要选择在什么时候去给Category赋值

  • 选择一:立刻给通过分类ID(CategoryID属性)去获取所属文章分类的对象,然后塞给文章所属分类属性(Category) ,然后再返回文章对象。这种方法在有一点不好,就是万一得到文章对象之后根本不用去使用到Category属性显然这种做法不佳。
  • 选择二:在需要的时候再去读取文章分类,然后给文章类对象的Category属性赋值,但这和没有这个属性其实也没有什么区别。
  • 选择三:在Category属性的get访问器中实现读取数据库获取文章分类的代码,这样如果没有使用到Category属性的 时候是不会调用到这些代码的,也就不会去访问数据库拿东西了,为了避免每次访问Category属性都去读取数据库, 我们给他增加一个所有字段,得到的代码如下:

    
    

    c#代码

    protected Model.ArticleCategory _category;
    public Model.ArticleCategory Category
    {
    get
    {
    if(_category == null)
    {
    // 创建文章分类数据访问层对象
    Dal.ArticleCategory articleCategoryDal = new Dal.ArticleCategory();
    // 获取文章分类
    _category = articleCategoryDal.GetArticleCategoryByCategoryID(CategoryID);
    }
    return _category;
    }
    // set访问器就不需要了
    }

  乍看起来似乎没问题,但要考虑一点,在三层结构中数据的传输靠的就是模型层,模型层处于三层之下, 换句话说,模型层不会去引用三层中的任何一层,而上面代码中的GetArticleCategoryByCategoryID很显然是在三层之中,也许是在业务逻辑层或者数据访问层,所以...循环引用了,这种做法也不佳。如何实现对在文章类中对Category属性的数据进行延时加载呢?整理思路,根据需求一步步分析:

乍看起来似乎没问题,但要考虑一点,在三层结构中数据的传输靠的就是模型层,模型层处于三层之下,

换句话说,模型层不会去引用三层中的任何一层,而上面代码中的GetArticleCategoryByCategoryID很显然

是在三层之中,也行是在业务逻辑层或者数据访问层,所以...循环引用了,这种做法也不佳。

  • 首先:获取到一个文章类对象的时候,只有在读取了Category属性才去访问数据库,不读取是不访问的
  • 其次:读取同一个文章类对象的Category属性的时候只访问一次数据库
  • 最后:在Category属性的get访问器中我们不能调用三层中的方法(严格说是不直接显示调用)

  换个角度思考,我们能不能在数据访问层中读取数据、初始化一个文章类对象之后给它一个方法,告诉它如果你要 获取自己所属分类信息(文章分类对象)的时候就调用这个方法来拿,不用的时候就不去调用了,免得多链读取一次数据库。 给它一个方法,也就是说把方法传给它咯! 于是想到委托,我们可以在文章类中添加一个委托,这个委托的签名和通过文章分类ID获取文章分类对象 方法的签名一致,在Category属性的get访问器中调用这个委托,这样便解决了可以在get访问器中调用到方法去访问数据库, 也自然实现了延时加载!于是修改实体类代码如下:


c#代码

namespace Model
{
// 文章分类实体类
public class ArticleCategory
{
public int CategoryID { get; set; }
public string CategoryName { get; set; }
}
// 文章实体类
public class Article
{
public int ArticleID { get; set; }
public string Title { get; set; }
public string Cotnent{ get; set; }
public DateTime CreateTime { get; set; }
public int CategoryID { get; set; }

// 文章所属分类
protected Model.ArticleCategory _category;
public Model.ArticleCategory Category
{
get
{
if (_category == null)
{
if (CategoryLazyLoader != null)
{
_category = CategoryLazyLoader(CategoryID);
}
else
{
_category = null;
}
}
return _category ;
}
}
// 文章分类延时加载器(委托)
public Func<int, Model.ArticleCategory> CategoryLazyLoader { get; set; }
}
}

  在文章读取数据库得到数据然后创建一个文章类对象之后,我们对CategoryLazyLoader进行赋值就OK了! 文章数据访问类中获取文章的方法大致如下:


c#代码

// 根据文章ID获取文章实体类对象
public Model.Article GetArticleById(int articleId)
{
// 从数据库中取出数据,得到一个DateRow或者DateRader之类的东东然后初始化一个文章实体类对象
Model.Article article = ... // ...是代码 - -!
// 创建文章分类数据访问对象
Dal.ArticleCategory articleCategory = new Dal.ArticleCategory();
// 指定延时加载委托
article.CategoryLazyLoader = articleCategory.GetArticleCategoryById;
// 返回文章对象
return article;
}

  通过上面方法得到的文章实体类对象中的Category属性就是实现了延时加载的了!
  文章写得不短,不过说的东西很简单,细想起来几乎没什么内容,一句话就是使用委托预先得到一个用于获取文章分类的方法,在文章分类属性的get选择器中调用委托返回结果。好了,告诉负责编写UI层代码的同事,调用了业务逻辑层的方法去获取文章实体类对象吧,! 已经帮你把文章分类给封装加进去了,而且使用了延迟加载,怎么实现你就不用管,用就行了!于是这个人用的时候囧了,文章实体类对象里面有个委托...... 委托啊!!!干嘛用的!!!???啥意思!

  先写到这里了,下一篇文章再说一些怎么隐藏这个委托,了解延迟加载的同学应该也想到方法了...

时间: 2024-09-30 02:43:51

一起谈.NET技术,浅谈C#中的延迟加载(1)——善用委托的相关文章

吴佰元:浅谈GPS技术在国土资源中的应用

[硅谷网9月26日讯]原文载于<科技与生活>杂志2012年第14期,文章称,社会在不断的前进与发展,当代信息化的时代里,对于各项技术的发展来讲,都是具有十分良好的前景与较大的发展空间.所以这些新技术的出现,为社会为人们的生活带来很多的便利.因此,在当代我们要充分利用这些新技术.新产品的力量推动我国各项事业不断前进的步伐. 关键词GPS技术:http://www.aliyun.com/zixun/aggregation/30834.html">国土资源:应用 国土资源是国民经济中

技术人员谈管理之浅谈团队管理

古语云":马,匹马徘徊,万马奔腾;人,单影单身难行,合群大成."团队是由一些拥有互补技能,为了共同目标而遵循共同方法和行为规则,相互承担责任的人组成的群体. 谈团队管理就不能不提人力资源管理,人力资源管理简单的理解就是管人,由于人才是企业最重要的财富,因此人力资源管理的重要性可想而知. 人力资源管理的过程包括如下4个方面: 1.      制定人力志愿计划 人力资源计划包括识别和记录项目角色.责任和汇报关系. 2.      组建项目团队 组建团队就是找人,为项目工作找到所需的人员以及

一起谈.NET技术,ASP.NET中如何正确使用Session

Asp.Net中的Session要比Asp中的Session灵活和强大很多,同时也复杂很多:看到有一些Asp.Net开发人员报怨说Session不稳定,莫名其妙的丢失,其实这正是Asp.Net改进的地方之一. 我们知道Session与Cookie最大的区别在于:Cookie信息全部存放于客户端,Session则只是将一个ID存放在客户端做为与服务端验证的标记,而真正的数据都是放在服务端的内存之中的. 在传统web编程语言(比如asp)中,session的过期完全是按照TimeOut来老老实实处理

一起谈.NET技术,从.NET中委托写法的演变谈开去(上):委托与匿名方法

在<关于最近面试的一点感想>一文中,Michael同学谈到他在面试时询问对方"delegate在.net framework1.1,2.0,3.5各可以怎么写"这个问题.于是乎,有朋友回复道"请问楼主,茴香豆的茴有几种写法","当代孔乙己",独乐,众乐.看了所有的评论,除了某些朋友认为"的确不该不知道这个问题"之外,似乎没有什么人在明确支持楼主. 不过我支持,为什么?因为我也提过出这样的问题. 这样,我们暂且不提应

一起谈.NET技术,从.NET中委托写法的演变谈开去(中):Lambda表达式及其优势

在上一篇文章中我们简单探讨了.NET 1.x和.NET 2.0中委托表现形式的变化,以及.NET 2.0中匿名方法的优势.目的及注意事项.那么现在我们来谈一下.NET 3.5(C# 3.0)中,委托的表现形式又演变成了什么样子,还有什么特点和作用. .NET 3.5中委托的写法(Lambda表达式) Lambda表达式在C#中的写法是"arg-list => expr-body","=>"符号左边为表达式的参数列表,右边则是表达式体(body).参数列表

偷也是门技术——浅谈XMLHTTP应用:新闻小偷[转]

xml 本文参考互联网整理而成(在此感谢资料奉献者).希望本文尽量系统,尽量易懂. 偷,即无劳而获.在网络上,诸如某大型权威站点发布了新闻,而自己的小小站点也想与时俱进,和人家一样同步更新,多N啊.于是,偷就是最好的办法了.偷是不道德的,不鼓励偷,但又不提倡不偷,都是技术惹的祸,扯远了~! 小偷程序是什么? 其实是通过XML中的XMLHTTP对象调用其它网站上的网页,甚至可以将接受的HTML代码进行过滤以获得需要内容(比如提取某某气象站,不可能是将整站提取显示,而只是需要显示天气的那部分). 其

民用报警服务技术浅谈

报警行业的设备和系统数字化.网络化的速度在加快,未来的报警服务行业市场是网络化的专属,传统的报警服务商业模式正在发生变化,通过卖产品和施工实现盈利的方式在弱化.在互联网时代,报警服务企业在实现技术变现的时候,更多要依靠服务去获得市场和用户的认可. 相对于传统的报警设备,网络化的报警设备在布线和安装上都有了长足的进步,加上IPC的软硬件,以及移动端的开发应用,如今的报警操作系统不仅使用方便,提高用户的使用体验,还改变了传统报警的样式,使得接警人员对报警区域进行可视化联动操作,降低误报率和报警运营中

一起谈.NET技术,关于C# 中的Attribute 特性

Attribute与Property 的翻译区别 Attribute 一般译作"特性",Property 仍然译为"属性". Attribute 是什么 Attribute 是一种可由用户自由定义的修饰符(Modifier),可以用来修饰各种需要被修饰的目标. 简单的说,Attribute就是一种"附着物" -- 就像牡蛎吸附在船底或礁石上一样. 这些附着物的作用是为它们的附着体追加上一些额外的信息(这些信息就保存在附着物的体内)-- 比如&qu

一起谈.NET技术,.Net语言中关于AOP 的实现详解

文章主要和大家讲解开发应用系统时在.Net语言中关于AOP 的实现.LogAspect完成的功能主要是将Advice与业务对象的方法建立映射,并将其添加到Advice集合中.由于我们在AOP实现中,利用了xml配置文件来配置PointCut,因此对于所有Aspect而言,这些操作都是相同的,只要定义了正确的配置文件,将其读入即可.对于Aspect的SyncProcessMessage(),由于拦截和织入的方法是一样的,不同的只是Advice的逻辑而已,因此在所有Aspect的公共基类中已经提供了

安卓AOP三剑客之Android APT技术浅谈

通过学习与使用square公司的开源项目javapoet,来实现仓库层动态生成代码 安卓AOP三剑客: APT, AspectJ, Javassist Android APT APT(Annotation Processing Tool 的简称),可以在代码编译期解析注解,并且生成新的 Java 文件,减少手动的代码输入.现在有很多主流库都用上了 APT,比如 Dagger2, ButterKnife, EventBus3 等 代表框架: DataBinding Dagger2 ButterKn