对使用CodeSmith模板生成NHibernate的代码的分析

       CodeSmith是我们常用的代码生成工具,其跟据不同的模板生成不同代码的方式能大大加快我们的项目开发,减少重复劳动。NHibernate模板就是其常用模板之一。从这里可以下载到最新的模板文件。现在最新的版本为NHibernate-v1.2.1.2125,可以生成NHibernate1.2,2.1,3.0的代码。我下载的稍早,是NHibernate-v1.1.7.2056,最高生成2.1的代码,不过大同小异,就以我下载的版本来进行分析吧。

 

      基本生成操作就不说了,官网上有讲解的视频,也有大把的网友做了专门的教程。代码生成后,主要分为五大块:

      1.Base块,也就是基类块,这里放有BusinessObjects块,ManagerObjects块,UnitTests块的基类,还包括一个作者提供我们的一个管理NH的ISession的小模块:NHibernateSessionManage块。

      2.BusinessObjects块,也就是我们常说的实体(Entity/Model)块。里面放置着与数据库表一一对应的各个实体。

      3.HbmMaps块,NH必用,不多讲。

      4.ManagerObjects块,也就是我们常说的BL层,里面包括了对每个实体的操作类,命名方式类似于XXXManage等等。另外还有一个小工厂,通过不同的方法实例化不同的管理类,比较简单,不表。

      5.UnitTests块,测试用例块,这不是我们今天谈的重点,故不多述。

 

      从上面可以看到,NH模板生成的代码是典型的三层架构式代码,采用的架构模式是活动记录式。 更详细的概念描述请自行Google,或者参见我另两遍博文:业务逻辑架构模式(事务脚本,表模块,活动记录,领域模型),再谈业务逻辑架构模式(事务脚本,表模块,活动记录,领域模型)。

      由于Base块里面的基类与下面三块里的子类的关系较大,所以我将按照BusinessObjects块,ManagerObjects块,NHibernateSessionManage块的顺序来讲述,在讲述的过程中直接将基类一起表述。例子就参见下面的一张图,其中Aim是实体类,AimManage是其对应的管理类。

      

      首先是BusinessObjects块,其实我们更常见的叫法是实体层。Aim是我们自己的实体,BusinessBase<T>是其基类,其中T这个泛型是指主键的类型,如果是联合主键,这里则不会是基本类型,而是会单独生成一个类,这个类的属性与联合主键的每一个子元素一一对应。BusinessBase<T>实现了IBusinessBase<T>接口,在这个接口里规定了一个很重要的属性:Id,其类型由T来指定,这表明了所有表的主键的在代码里都叫Id。当然,如果实际的表中的主键不叫Id也是没有关系的,实体的配置文件hbm.xml可以解决这个问题。这个接口还有两个方式:GetHashCode和Equals,比较简单,不多表。

 

      再来看ManagerObjects块,对于这我们也有更常见的叫法:BL层或者是业务逻辑层。

     

      从上向下讲,最开始是个IManagerBase<T, TKey>接口,其中T是指其管理的实体类别,TKey是其管理的实体的主键类型。在这个接口中定义了常见的实体操作方式:增删改和各种形势的通用的查询。ManagerBase<T, TKey>类则是其具体的实现。IAimManage是具体实体管理类的接口,里面定义了具体实体所具有的特定的操作方法,注意,这里继承了IManagerBase<T, TKey>接口,这是很重要的一点,等下表述。最后是AimManage类,其继承了ManagerBase<T, TKey>类和IAimManage接口。从前者获取通用操作的实体,从后者获取定义的特定操作并由自己来实现。这里就要讲为什么IAimManage接口要继承IManagerBase<T, TKey>。从编译的角度来讲,前者不继承后者依然可以通过编译,但从我们架构代码的角度来讲,当编码中我们要操作AimManage类时,有两种方式,一种是直接通过本类型操作:

AimManage manage = new AimManage();

一种是通过接口操作:

IAimManage manage = new AimManage();

为了减少代码耦合,通过接口操作是比较理想的方式。如果前者不继承后者,当出现后者的代码时,我们就无法通过manage来操作AimManage类从ManagerBase<T, TKey>类继承到的通用操作了。换种说法,由于ManagerBase<T, TKey>类继承并实现了IManagerBase<T, TKey>接口,AimManage类又继承了ManagerBase<T, TKey>类,那么实际上AimManage类间接继承并实现了IManagerBase<T, TKey>接口。现在AimManage类又继承并实现了IAimManage接口,从多继承的角度来讲,各个接口只能操作其子类从本接口继承而来的属性与方法,如下图:

 

如果IAimManage接口没有继承IManagerBase接口,那当代码是这么写的时候:

IAimManage manage = new AimManage(); 

变量manage是无法执行A()方法的,因为A()方法从IManagerBase接口而来。

 

      最后看看NHibernateSessionManage块,这是作者为我们提供的一个Session管理模块,包括两个类与两个接口。这个模块通过接口的方式与其它模块交互的少,故不多表,主要讲讲两个类的使用:NHibernateSessionManager类与NHibernateSession类。NHibernateSession类是作者为我们重新封装的Session类,他将始的ISession接口封装了进去,目的是代替NH原始的ISession接口。里面有两个重要的成员ISession和ITransaction。其中ISession就是NH的原始的ISession接口。由于他在这里将原始的ISession接口封装了进去,通过其操作事务就不是很方便,于是作者就使用成员ITransaction将ISession内的ITransaction引用出来,并写了一大堆方法来完成对事务的操作。还有一个方法:GetISession()来获取原始的ISession。

 

      NHibernateSessionManager类是具体的Session管理类。他通过静态变量Instance实现了单例模式。他有一个重要的属性Session和一个重要的方法CreateISession()。通过Session属性来获取本次操作的NHibernateSession类。可以看到,作者将每次操作的NHibernateSession放到了缓存中(webForm与winForm放置的地方不同),提高了性能。CreateISession()方法则是真正获取原始ISession的方法,NHibernateSession类的GetISession()方法调用的也是他。

public ISession GetISession()
{
    
if (iSession == null)
        iSession 
= NHibernateSessionManager.Instance.CreateISession();
    
return iSession;
}

       回到ManagerBase<T, TKey>类,在其两个构造函数中:

public ManagerBase()
    : 
this(NHibernateSessionManager.Instance.Session) { }
public ManagerBase(INHibernateSession session)
{
    
this.session = session;
    
this.session.IncrementRefCount();
}

       默认就是调用NHibernateSessionManager类单例实例的Session属性,或者通过自定义INHibernateSession来注入。

 

      以上就是代码分析的全过程,可以看出,生成的代码精干紧凑,使用方便,是我们学习三层架构模式,活动记录模式和生产实践的良好示范。

转载于:https://www.cnblogs.com/ljzforever/archive/2011/03/14/1983121.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/275608.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

若川诚邀你加源码共读群,每周一起学源码

小提醒&#xff1a;若川视野公众号面试、源码等文章合集在菜单栏中间【源码精选】按钮&#xff0c;欢迎点击阅读&#xff0c;也可以星标我的公众号&#xff0c;便于查找。回复pdf&#xff0c;可以获取前端优质书籍。最近我创建了一个源码共读的前端交流群&#xff0c;希望尝试帮…

matlab 规范,matlab-代码-规范

matlab-代码-规范 1. 标识符命名原则 标识符的名字应当直观&#xff0c;其长度应当符合“最小长度&#xff0c;最大信息量”原则。 1) 非矩阵变量&#xff1a; 变量名应该以小写字母开头的大小写混合形式 譬如&#xff1a;shadowFadingTable&#xff0c;servingSector&#xf…

zoom视频会议官网_人性化视频会议的空间(Zoom等)

zoom视频会议官网第二部分&#xff1a;房间的创造力 (Part Two: The Creativity of Rooms) In Part One I shared thoughts on how virtual spaces can often leave little room to embody our most human selves. The lack of a public sphere that parallels our shared publ…

KOFLive Postmortem

为期两个月的团队项目完成了&#xff0c;我们的游戏也已经发布。在这个名叫KOFLive的小游戏里&#xff0c;我们集成了五个真人角色&#xff0c;每个角色有拳脚基本招数以及三个小招、一个大招&#xff0c;硬值、防御、集气、双人对战、人机对战、练习模式等格斗游戏的Feature基…

单调队列优化多重背包

就是按照 % 体积的余数来分组&#xff0c;每组单调队列优化。 直接上模板好了。 1 #include <bits/stdc.h>2 3 typedef long long LL;4 const int N 100010;5 6 int n, V, cnt[N], cost[N];7 LL f[2][N], val[N], p[N], top, head;8 9 inline void Max(LL &a, const…

2021年7月 虾皮、货拉拉、有赞等面经总结

大家好&#xff0c;我是若川&#xff0c;加我微信 ruochuan12 进源码交流群。今天分享一篇7月份新鲜出炉的面经&#xff0c;文章较长&#xff0c;可以收藏再看。学习源码系列、面试、年度总结、JS基础系列。本文来自作者几米阳光 投稿 原文链接&#xff1a;https://juejin.cn/p…

Oracle对表名大小写敏感吗,让Oracle 大小写敏感 表名 字段名 对像名

一、解决方案1、在表名、字段名、对象名上加上双引号&#xff0c;即可实现让oracle大小写区分。2、但是这又引起了另一个问题&#xff1a;在数据库操作中&#xff0c;sql语句中相应的表名、字段名、对象名上一定要加双引号。解决办法是&#xff1a;使用"\"转义。如&a…

谷歌抽屉_Google(最终)会杀死导航抽屉吗?

谷歌抽屉A couple of months ago Google has celebrated with enthusiasm 15 years of Google Maps, one of the most used and appreciated services worldwide from the company.几个月前&#xff0c;Google热情地庆祝Google Maps诞生15周年&#xff0c;这是该公司在全球范围…

MySQL——安装

MySQL——安装 1. 下载源&#xff1a; http://repo.mysql.com/yum/mysql-8.0-community/el/7/x86_64/mysql80-community-release-el7-2.noarch.rpm 该源目前为8.0版本&#xff0c;如果需要最新请退至根目录找。 1wget http://repo.mysql.com/yum/mysql-8.0-community/el/7/x86_…

写给初中级前端的高级进阶指南等

大家好&#xff0c;我是若川。话不多说&#xff0c;这一次花了几小时精心为大家挑选了20余篇好文&#xff0c;供大家阅读学习。本文阅读技巧&#xff0c;先粗看标题&#xff0c;感兴趣可以都关注一波&#xff0c;绝对不亏。程序员成长指北考拉妹子&#xff0c;一个有趣的且乐于…

oracle for函数,oracle分区表述的FOR语句(一)

指定一个分区除了使用分区名称外&#xff0c;很多时候还可以使用FOR语句。从11g开始&#xff0c;对分区进行操作的时候&#xff0c;不仅可以使用分区名称&#xff0c;还可以使用FOR语句。在10g中&#xff0c;MERGE RANGE分区的语句如下&#xff1a;SQL> SELECT * FROM V$VER…

axure9控件树 rp_如何在Axure RP 9中创建分段控件

axure9控件树 rpSegmented controls are not very easy to tackle in prototyping. This is especially true when you have more than 2 segments. This article will show you how to create a segmented control with 3 segments in Axure in just 2 simple steps. The tech…

stack

1. 栈数据结构简单介绍 2. 简单实现代码及stl中stack简单使用 3. 代码下载 1. 栈数据结构简单介绍 栈是这样的一种数据结构&#xff0c;遵循“先进后出”的原则。在stack上定义如下的operations&#xff1a; 1. 判空 2. 入栈push 3. 出栈pop&#xff0c;在栈的不同实现版本中&…

MacOS搭建环境

基础环境 从AppStore下载 有道云笔记微信网易云音乐Chrome浏览器postmanChrome插件云笔记剪报基础命令 mac下别名vi ~/.bash_profile 添加 alias llls -alF alias lals -A alias lls -CF 保存后执行(不能有空格) source ~/.bash_profile复制代码开发环境 PhpStorm 从官网下载Ph…

【送书-小姐姐配音】低代码平台的核心价值与优势

大家好&#xff0c;我是若川。记得点上方听小姐姐配音&#xff0c;识别下方二维码加我微信 ruochuan12&#xff0c;明天&#xff08;8月8日&#xff09;晚8点在朋友圈发动态。点赞抽3位小伙伴包邮送《实战低代码》&#xff0c;细则见动态。最近组织了源码共读活动&#xff0c;每…

oracle静默安装集群,静默安装Oracle数据库10g篇

静默安装Oracle数据库10g篇以下是在Linux系统上静默安装Oracle数据库10g的实践过程&#xff0c;主要分为以下两个步骤&#xff1a;Step 1&#xff0e;静默安装Oracle数据库10g软件1. 使用OUI录制响应文件&#xff0c;记录安装过程执行以下命令&#xff0c;然后在OUI中根据提示执…

sketch钢笔工具_设计工具(Sketch,Adobe XD,Figma和InVision Studio)中奇怪的一项功能

sketch钢笔工具When you build a new product that is very similar to the existing products in the market, the designers and product managers tend to do certain features different from others. Sometimes this brings a good change, sometimes worse.当您构建与市场…

modprobe:FATAL: could not load /lib/modules/2.6.35-22-generic/modules.dep No such file or directory

给ubuntu升级到10.10 &#xff0c;开机可能出现错误modprobe:FATAL: could not load /lib/modules/2.6.35-22-generic/modules.dep No such file or directorymodprobe:FATAL: could not load /lib/modules/2.6.35-22-generic/modules.dep No such file or directory解决办法&a…

Python进阶:如何将字符串常量转化为变量?

2019独角兽企业重金招聘Python工程师标准>>> 前几天&#xff0c;我们Python猫交流学习群 里的 M 同学提了个问题。这个问题挺有意思&#xff0c;经初次讨论&#xff0c;我们认为它无解。 然而&#xff0c;我认为它很有价值&#xff0c;应该继续思考怎么解决&#xf…

怎么在matlab中图像中外接矩形,Matlab 最小外接矩形

Matlab 中并没有发现最小外接矩形的代码&#xff0c;为了方便下面提供最小外接矩形的代码&#xff1a;注&#xff1a;这个函数是源于网上找到的代码的改进版&#xff0c;原版不能检测水平线或者垂直线function [rectx,recty,area,perimeter] minboundrect(x,y,metric)% minbou…