zoukankan      html  css  js  c++  java
  • 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才证实这点。

    配置文件如下: 

    TestSeq.hbm.xml
    <?xml version="1.0" encoding="utf-8" ?>
    <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后的配置文件如下:

    TestSeq.hbm.xml
    <?xml version="1.0" encoding="utf-8" ?>
    <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 c = domainService.AddTestSeq(new DomainModel.Entities.TestSeq() { NAME = DateTime.Now.ToString() });
                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 a = domainService.GetTestById3(1);
                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的二级缓存扩展还比较感兴趣,因为这个直接影响到最终用户,希望以后可以多熟悉这块。

  • 相关阅读:
    如何使用dom拼接xml字符串(标准方式)
    javascript默认将数字类型的“002,00123”,作为整数,去掉前面的0
    java学习小记
    如何将div排成一行显示(默认垂直显示)
    【转】JDBC调用存储过程之实例讲解
    数组求和算法系列
    《12个球问题》分析
    C#类在什么时候分配内存
    C++请不要问我string s=”a”+”b”分配了几次内存
    算法两道百度笔试题
  • 原文地址:https://www.cnblogs.com/Lawson/p/1897085.html
Copyright © 2011-2022 走看看