注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

天涯倦客的博客

祝福你朋友永远快乐!

 
 
 

日志

 
 

浅谈C#中的延迟加载(2)——善用virtual  

2012-12-27 22:44:38|  分类: asp.net |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
  之前的文章“浅谈C#中的延迟加载(1)——善用委托”中介绍了三层结构中在Model层对实体类的属性实现延迟加载的方法,该方法利用C#中的委托来实现,最后虽然延迟加载的目的得以实现,但是给客户端(例如UI层)暴露了不必要的属性(一个委托对象,我使用了泛型的Fun类来实现)。这篇文章介绍一种方法来隐藏这个属性,同时又可以达到延迟加载的目的,更重要的是这一切都是在之前的基础上来完成的,不需要改变原来使用到实体类的地方的代码。

    按照惯例,我们考虑一下想要我们的代码达到什么效果:首先在Model.Acticle(文章实体类)中的Category属性和原来一样,只在需要的时候通过调用委托来获取文章所属分类(Model.ArticleCategory类)。同时这个委托是不被客户端(例如UI层)代码看到的。。。设计模式中有一句话,大致的意思是“通常在两个事物之间加上一个中间层,可以把事情变得简单”,于是我们这样考虑,能不能加多一个中间层来实现呢? 把Category属性定义为虚拟的(virtual),去掉委托,继承Model.Acticle类实现一个子类,把委托放到到这个子类里面来,由个子类里面去实现Category属性的get选择器,客户端访问的是一个用该子类做实例化的Model.Acticle类对象,这样一来客户端代码访问的依旧是Model.Acticle类,但是看不到用于实现延迟加载的委托却又能在Category属性中获取到需要的数据。呵呵,由于我是写文章的人,所以觉得这个思路很好理解,但是看文字的您可能感觉有点晕,下面用代码来说明应该就清楚了。

    首先我们修改Model.Acticle类,给他瘦身,瘦身结果如下:
   
    // 文章实体类
    publicclassArticle
    {
        publicintArticleID { get; set; }
        publicstringTitle { get; set; }
        publicstringCotnent{ get; set; }
        publicDateTime CreateTime { get; set; }
        publicintCategoryID { get; set; }
        
        // 所属分类
        publicvirtualModel.ArticleCategory Category
        {
            get;
        }
    }

    对比上一篇文章,可以发现作为延迟加载用的委托不见了,另外就是Category的get选择器中不再有任何逻辑代码,并且该属性被声明为virtual了。

    下一步我们创建多一层出来。新建一个名为DModel的类库(注意:该层需要引用Model层,然后被Dal层引用)。接下来在DModel层也创建一个Article类,没错!用他来继承Model.Acticle类。Dmodel.Acticle长成下面这个样子:
   
namespaceDModel
{
    // 文章
    publicclassArticle : Model.Article
    {
      // 文章所属分类
      protected Model.ArticleCategory _category;
        publicoverrideModel.ArticleCategory Category
        {
            get
            {
                if(_category == null)
                {
                    if(CategoryLazyLoader != null)
                    {
                        _category = CategoryLazyLoader(CategoryID);
                    }
                    else
                    {
                        _category = null;
                    }
                }
                return _category;
            }
        }
        // 文章分类延时加载器(委托)
        publicFunc<int, Model.ArticleCategory> CategoryLazyLoader { get; set; }
    }
}

    是的,看到了么,委托跑这儿来了,并且他实现了Model.Acticle的Category属性的get选择器,里面的逻辑是不是也很熟悉呢^_^。

    接着还有一个地方要做点小修改,就是Dal层中获取一个文章实体类的方法,也就是前一篇文章中写到的public Model.Article GetArticleById(int articleId)方法了,修改后如下:

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


    请注意上面代码中这一句,DModel.Article article = ... // “...”是代码 - -!,我们得到一个DModel.Article对象,最后以Model.Article的形式返回(C#中的装箱,是吧~)。再次告诉你的同事吧,你不用去管那个委托了,因为你现在拿到的Mode.Article对象中看不到那玩意,反正对你也没用。果然,看不见了,延迟加载的目的也达到鸟!
    总结一下,本文讲的比前一篇文章讲的东西还少,主要记住三点:
        1、把Category属性声明为虚拟的;
        2、把Category原来的逻辑代码推迟到子类里面实现;
        3、用子类(DModel.Acticle)实例话父类(Model.Acticle)。

    好了,用这个方法把项目里面类似Category这样的实体类属性修改为virtial吧,创建子类去重写它实现延迟加载,子类只有Dal层知道它的存在,Bll层和UI层对此一无所知,他们还是和原来一样用着,啥都不用修改,但是代码的效率明显有了提高,现在属性没有被使用就不会读取数据库了,数据库的压力也减少了^_^!!!

from:http://www.cnblogs.com/serafin/archive/2011/01/15/1936324.html
  评论这张
 
阅读(482)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017