Nhibernate连接oracle数据库,主键ID用序列生成时连接数据库IO次数分析
本来打算主键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的二级缓存扩展还比较感兴趣,因为这个直接影响到最终用户,希望以后可以多熟悉这块。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· [AI/GPT/综述] AI Agent的设计模式综述