本来打算主键ID用触发器生成,因为程序只需要一次IO就能插入一条数据。
图在下面,这里assigned不能改为native,从配置中看,是程序来生成ID,但实际oracle接受到插入消息后,触发器自动用序列替换了ID,因此遇到一个问题,就是程序不能获取到刚才插入的实体的主键ID,于是改为配置文件中指定序列创建ID,为了看它生成的sql和连接数据库的IO次数,我用NHibernateProfiler和sql server profiler进行了检测,oracle没找到好的检测连接sql的工具,因此用mssql的检测工具检测了下。用NHibernateProfiler检测生成sql时,迷惑了我,由于一系列的执行我共享了session,该工具都只显示一个session,并且列出它生成了哪些sql,让我以为它只是一个IO就把整个查询和操作弄好了,nhibernate的默认延时加载好像是如果同一个session中没有相同对象,然后从数据库获取对象,但该对象内部的其他对象会延时加载,并且他检测出的sql,并不是真正数据库获取到查询sql,比如查询都参数化了,但NHibernateProfiler没有很细的说明查询的值是什么参数,这在我查询序列的创建和传递给插入实体对象的sql时没看明白,我用sql server profiler才证实这点。
配置文件如下:
< hibernate-mapping xmlns ="urn:nhibernate-mapping-2.2" assembly ="DomainModel" namespace ="DomainModel" >
< class name ="DomainModel.Entities.TestSeq,DomainModel" table ="TESTSeq" >
< id name ="ID" column ="ID" type ="int" >
< generator class ="assigned" ></ generator >
</ id >
< property name ="NAME" column ="NAME" type ="string" />
</ class >
</ hibernate-mapping >
该为指定序列生成ID后的配置文件如下:
< hibernate-mapping xmlns ="urn:nhibernate-mapping-2.2" assembly ="DomainModel" namespace ="DomainModel" >
< class name ="DomainModel.Entities.TestSeq,DomainModel" table ="TESTSeq" >
< id name ="ID" column ="ID" type ="int" >
< generator class ="sequence" >
< param name ="sequence" > TestSeq1 </ param >
</ generator >
</ id >
< property name ="NAME" column ="NAME" type ="string" />
</ class >
</ hibernate-mapping >
程序c#代码执行数据库语句如下:
var a = domainService.GetTestById( " 002 " );
var b = domainService.GetTestById( " 003 " );
用NHibernateProfiler检测如下:
看不到参数化的sql,能看到执行的sql,但看不出连接数据库的次数。于是我改为连接sql server,用sql server profiler检测了下连接的sql,由于mssql没有序列的说法,因此只能看共享同一个session生命周期时,所有操作数据库的sql,数据库这边检测到的sql查询次数,
配置文件如下:
<id name="Id" column="Id" type="Int32" unsaved-value="0">
<generator class ="native"></generator>
</id>
其他都一样,
c#代码如下:
var a2 = domainService.GetTestById3( 1 );
var b = domainService.GetTestById3( 2 );
object o2 = domainService.AddTest( new DomainModel.Entities.Test() { name = " ab " });
用NHibernateProfiler检测如下:
用sql server profiler检测如下:
能明显看到有3次数据库的打开关闭操作,因此我判断虽然nhibernate共享一个session,部分操作感觉像是一个整体的执行,而且只是查询操作时,NHibernateProfiler会把所有查询操作的sql完了或者有插入数据库操作时,才在界面上显示查询的几次sql记录,但NHibernateProfiler实际上还是对界面short sql中的每行记录都有一次连接和关闭数据库的查询操作,配置用序列创建主键ID时,从NHibernateProfiler显示也是两次数据库的查询操作。
对NHibernate还不够熟,李永京的nhibernate系列文章还不错,要多学习学习,NH3又多了些特征和功能,但我对NHibernate的二级缓存扩展还比较感兴趣,因为这个直接影响到最终用户,希望以后可以多熟悉这块。