NHibernate性能的思考

“省事的活多半效率不高”,对编程来说,很多时候适用。NHibernate省却我们写Sql语句、存储过程,且数据库的移植又是相当方便,效率估计有一些影响。

那影响有多大呢?

为此我利用一个现有的WebService,试图去比较使用NHibernate和直接使用SqlClient之间的性能差异。

private ISessionFactory _sessions;
public void Configure()
{
    Configuration cfg 
= new Configuration();
    cfg.SetProperty(
"hibernate.connection.provider","NHibernate.Connection.DriverConnectionProvider");
    cfg.SetProperty(
"hibernate.dialect","NHibernate.Dialect.MsSql2000Dialect");
    cfg.SetProperty(
"hibernate.connection.driver_class","NHibernate.Driver.SqlClientDriver");
    cfg.SetProperty(
"hibernate.connection.connection_string","Server=localhost;initial catalog=Supercargo;user id=sa;password=network");

    cfg.AddClass(
typeof(Supercargo.Batch));
    cfg.AddClass(
typeof(Supercargo.Product));
    cfg.AddClass(
typeof(Supercargo.BatchItem));
    
this._sessions = cfg.BuildSessionFactory();
}


每一次的都从头到尾执行一次
this.Configure();
ISession session 
= _sessions.OpenSession();
ITransaction transaction 
= session.BeginTransaction();

session.Save(product1);
transaction.Commit();
session.Close();

SqlClient也一样从头到尾
SqlConnection connect = new SqlConnection("Server=localhost;initial"); 
try
{
    connect.Open();
    
    SqlCommand cmd 
= new SqlCommand(sql,connect);
    cmd.ExecuteNonQuery();
}

catch(Exception ee)
{
    str
= string.Format("语句:{0} \r\n错误:{1}",sql, ee.Message);
}

connect.Close();

执行100次的以上操作,NHibernate用了近6秒,直接使用SqlClient却用了不到2秒。NHibernate真的如此不济?

稍作思考,将NHibernate的过程分解了一下。首先使用一个类包装一下Configure
/// <summary>
/// DbConfigure 的摘要说明。
/// </summary>

public class DbConfigure
{
    
/// <summary>
    
/// 获取 Web应用程序的当前配置
    
/// </summary>

    public static DbConfigure CurrentConnect
    
{
        
get
        
{
            DbConfigure con 
= null;
            
object obj = System.Web.HttpContext.Current.Application["Connect"];
            
if(obj == null)
            
{
                con 
= new DbConfigure();                    
                System.Web.HttpContext.Current.Application[
"Connect"= con;
            }

            
else
                con 
= (DbConfigure)obj;

            
return con;
        }

    }


    
/// <summary>
    
/// 构造函数
    
/// </summary>

    public DbConfigure()
    
{                
        
this.configure();        
    }


    
/// <summary>
    
/// 打开连接。
    
/// </summary>
    
/// <returns></returns>

    public ConnectSession OpenSession()
    
{
        
return new ConnectSession(this._sessions.OpenSession());
    }
                        

    
private ISessionFactory _sessions;
    
private void configure()
    
{        
        Configuration cfg 
= new Configuration();
        cfg.SetProperty(
"hibernate.connection.provider","NHibernate.Connection.DriverConnectionProvider");
        cfg.SetProperty(
"hibernate.dialect","NHibernate.Dialect.MsSql2000Dialect");
        cfg.SetProperty(
"hibernate.connection.driver_class","NHibernate.Driver.SqlClientDriver");
        cfg.SetProperty(
"hibernate.connection.connection_string","Server=localhost;initial catalog=Superca");
        cfg.AddClass(
typeof(SD.Supercargo.Batch));
        cfg.AddClass(
typeof(SD.Supercargo.Product));
        cfg.AddClass(
typeof(SD.Supercargo.BatchItem));            
        
this._sessions = cfg.BuildSessionFactory();                
    }
        
}

也将ISession简单的封装到ConnectSession中
    /// <summary>
    
/// ConnectSession 的摘要说明。
    
/// </summary>

    public class ConnectSession
    
{
        
public ConnectSession(ISession pSession)
        
{            
            
this.mDbSession = pSession;
        }


        
public void Close()
        
{
            
this.mDbSession.Close();
        }


        
public void BeginTransaction()
        
{
            
this.mTransaction = this.mDbSession.BeginTransaction();
        }


        
public void CommitTransaction()
        
{
            
this.mTransaction.Commit();
        }


        
public void Update(object obj)
        
{
            
this.DbSession.Update(obj);
        }


        
public void Save(object obj)
        
{
            
this.DbSession.Save(obj);
        }


        
public void SaveOrUpdate(object obj)
        
{
            
this.DbSession.SaveOrUpdate(obj);
        }


        
private ITransaction mTransaction;
        
/// <summary>
        
/// 设置、获取Transaction
        
/// </summary>

        public ITransaction Transaction
        
{
            
get
            
{
                
if(this.mTransaction == null)
                    
this.mTransaction = this.mDbSession.BeginTransaction();
                
return this.mTransaction;
            }
            
        }

        
private ISession mDbSession;
        
/// <summary>
        
/// 获取DbSession
        
/// </summary>

        public ISession DbSession
        
{
            
get{return this.mDbSession;}            
            
set{this.mDbSession = value;}
        }

    }

测试过程只执行以下几步
DbConfigure con = DbConfigure.CurrentConnect;
ConnectSession connect 
= con.OpenSession();

ProductLocator prdLoc 
= new ProductLocator(connect.DbSession);
Product prd 
= new Product();
//一些赋值操作
connect.BeginTransaction();
prdLoc.Update(prd);
connect.CommitTransaction();
connect.Close();

NHibernate的成绩一下子提高到只需1.3秒多些,只稍慢于SqlClient的1.2秒,同样是操作100次。代码上的差异主要是用Application保存DbConfigure,Web应用程序只主要在启动的时候执行DbConfigure的Configure方法
public static DbConfigure CurrentConnect
{
    
get
    
{
        DbConfigure con 
= null;
        
object obj = System.Web.HttpContext.Current.Application["Connect"];
        
if(obj == null)
        
{
            con 
= new DbConfigure();                    
            System.Web.HttpContext.Current.Application[
"Connect"= con;
        }

        
else
            con 
= (DbConfigure)obj;

        
return con;
    }

}


当然对于windows应用程序就可以省下这个心了。看来NHibernate的是相当值得使用!
posted on 2006-02-08 15:06 生命体验之kevin-Y 阅读(5624) 评论(8)  编辑 收藏 网摘 所属分类: NHibernate

评论

#1楼  2006-03-19 12:11 YZX110_1 [未注册用户]   回复  引用    

没有说明查询的问题,一个系统中查寻效率很重要

#2楼 [楼主] 2006-03-21 13:25 生命体验之kevin-Y         回复  引用  查看    

@YZX110_1
在项目的建立、开发、维护阶段有很多东西是都很重要的。如果数据库的查询效率对你项目来说是最重要的话,ORM不应是你关系的技术。

#3楼  2006-07-16 15:56 林子         回复  引用  查看    

不错!

#4楼  2007-05-14 15:07 aaaaa [未注册用户]   回复  引用    

这样的测试无任何意义。
NHIBERNATE启动时,是预先把映射文件加载到内存中,每次加载需要较长时间。Configure文件不应该在每次对象操作就加载一次。

#5楼 [楼主] 2007-05-16 10:39 生命体验之kevin-Y         回复  引用  查看    

@aaaaa
谢谢5个a

#6楼  2007-06-21 17:18 Tei [未注册用户]   回复  引用    

Hibernate 的效率问题主要是批量操作上,由于要保证缓存中的数据同步,常常造成n+1的现象。但hibernate3好像改进了,比如批量删除时,不同步更新缓存数据。不知道NHibernate是怎么做的。刚刚学习c#,请多多指教。

#7楼  2007-09-07 11:43 walaqi [未注册用户]   回复  引用    

我也做了测试.在运行200次以内,Nhibernate1.2的性能同sqlclient不相上下(Console程序).但是200次以上,sqlclient用的时间明显比hibernate要少的多.尤其到了1000次以上,基本上是hibernate的50%以下.

#8楼  2008-06-18 14:53 gucs         回复  引用  查看    

2007 年以前,我对 orm 的理解就是“表和对象的映射”,所以感受不到 hibernate 的好。
后来我坐在了公司架构师的旁边,他和我说的 nhibernate 不再是个简单的 Mapping 工具了。
想用好 orm,你的设计首先要是 OO 的,这样就会出现 OO 和 ER 之间的不匹配,此时,就会用到 hiernate 了。
暂时,我还是没有用好 orm,因为我的设计不是完全 OO 的,呵呵

发表评论



姓名 [登录] [注册] 
主页
Email (仅博主可见) 
验证码 *  验证码看不清,换一张
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论   新用户注册   返回页首      

导航: 网站首页 社区 新闻 博问 闪存 网摘 招聘 .NET频道 知识库 找找看 Google站内搜索



China-pub 计算机图书网上专卖店!6.5万品种 2-8折!
China-Pub 计算机绝版图书按需印刷服务

相关文章:

相关链接: