NHibernate考察系列 02 使用入门 简单映射

NHibernate考察系列 02 使用入门 简单映射

    NHibernate入门示例。

    测试项目目录结构如下
    NHibernate考察系列 02 使用入门 简单映射_第1张图片

    建立一个Company类用来测试,对应的表为TBLCOMPANY。
    1. 下载NHibernate(版本1.2.0.CR1),将NHibernate \bin\net-2.0下面的文件拷贝到lib目录。
    2. 为实体建立Class Library的Domain工程。为工程添加\lib\Iesi.Collections.dll文件的引用(以后用)。
    3. Company类的代码如下
using  System;
using  Iesi.Collections.Generic;

namespace  NH12.MyExample.Domain
{
    
#region  Company
    
public   class  Company
    {
        
private   string  _companyID;
        
private   string  _companyName;

        
public  Company( string  id,  string  name)
        {
            _companyID 
=  id;
            _companyName 
=  name;
        }

        
public  Company()
        {
        }

        
public   virtual   string  CompanyID
        {
            
get  {  return  _companyID; }
            
set  { _companyID  =  value; }
        }

        
public   virtual   string  CompanyName
        {
            
get  {  return  _companyName; }
            
set  { _companyName  =  value; }
        }

        
#region  override
        
public   override   bool  Equals( object  obj)
        {
            
if  ( this   ==  obj)  return   true ;
            
if  (obj  ==   null   ||  obj.GetType()  !=   this .GetType())
                
return   false ;
            Company company 
=  obj  as  Company;
            
return  company  !=   null   &&  company.CompanyID  ==  _companyID;
        }

        
public   override   int  GetHashCode()
        {
            
return  _companyID.GetHashCode();
        }

        
public   override   string  ToString()
        {
            
return  _companyID;
        }
        
#endregion
    }
    
#endregion
}
    4.  将NHibernate源代码中的nhibernate-mapping.xsd文件拷贝到Domain工程的目录下,也可以拷贝到VS  2005的系统目录,这是因为映射文件使用这个xsd进行校验、输入提示等。
    为Domain工程添加Company.hbm.xml映射文件,在文件的属性->Build Action中选择Embedded Resource,文件内容如下
xml version="1.0" encoding="utf-8"  ?>
< hibernate-mapping  xmlns ="urn:nhibernate-mapping-2.2"  namespace ="NH12.MyExample.Domain"  assembly ="Domain" >
  
< class  name ="Company"  table ="TBLCOMPANY" >
    
< id  name ="CompanyID"   >
      
< column  name ="COMPANY_ID"  sql-type ="nvarchar"  length ="4"  not-null ="true" />
      
< generator  class ="assigned"   />
    
id >

    
< property  name ="CompanyName" >
      
< column  name ="COMPANY_NAME"  length ="70"  sql-type ="nvarchar"  not-null ="true"   />
    
property >
  
class >
hibernate-mapping >
    5. 添加一个Console Application的NHTest工程。为工程添加\lib\Iesi.Collections.dll、\lib\NHibernate.dll文件的引用,添加Domain项目引用。
    6. 将NHibernate源代码中的nhibernate-configuration.xsd文件拷贝到NHTest工程的目录下,也可以拷贝到VS  2005的系统目录,这是因为配置文件使用这个xsd进行校验、输入提示等。
    在NHTest的App.config文件中添加如下配置:
< configSections >
  
< section
      
name ="hibernate-configuration"
      type
="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate"
      
/>
configSections >

< hibernate-configuration  xmlns ="urn:nhibernate-configuration-2.2" >
  
< session-factory >
    
< property  name ="dialect" > NHibernate.Dialect.MsSql2000Dialect property >
    
< property  name ="connection.provider" > NHibernate.Connection.DriverConnectionProvider property >
    
< property  name ="connection.connection_string" > Server=localhost;initial catalog=NH;user id=sa;password=123 property >
    
< property  name ="connection.driver_class" > NHibernate.Driver.SqlClientDriver property >
    
< property  name ="use_proxy_validator" > False property >

    
< mapping  assembly ="Domain"   />
  
session-factory >
hibernate-configuration >
    数据库连接字符串信息改成自己的。注意1.2版本中配置信息不再支持方式,而改用property元素,相应的name只需要把原来name值中的nhibernate.这个前缀去掉就可以,value的方式没有发生变化。
    7. 写代码测试。测试代码如下:
using  System;
using  System.Collections.Generic;
using  System.Text;

using  NH12.MyExample.Domain;
using  NHibernate;
using  NHibernate.Cfg;
using  Iesi.Collections.Generic;

namespace  NH12.MyExample.Test
{
    
class  Program
    {
        
static   void  Main( string [] args)
        {
            ISessionFactory sessionFactory 
=   new  Configuration().Configure().BuildSessionFactory();
            ISession session 
=   null ;
            ITransaction trans 
=   null ;
            
try
            {
                session 
=  sessionFactory.OpenSession();
                trans 
=  session.BeginTransaction();

                Company company 
=   new  Company( " 1000 " " BenQ Guru Co., Ltd. " );
                session.Save(company);
                Console.WriteLine(
" company 1000 has been created " );

                Company company2 
=   new  Company( " 2000 " " test company 2 " );
                session.Save(company2);
                Console.WriteLine(
" company 2000 has been created " );

                Company company3 
=  session.Get < Company > ( " 1000 " );
                Console.WriteLine(
" Company : id: {0} name: {1} " , company3.CompanyID, company3.CompanyName);

                trans.Commit();
            }
            
catch  (Exception e)
            {
                trans.Rollback();
            }
            
finally
            {
                session.Close();
            }
            sessionFactory.Close();

            Console.ReadLine();
        }
    }
}
    现在可以运行这个最简单的映射示例,运行完之后可以在TBLCOMPANY表中查询到记录。

    即使是最简单的例子,我们也可以发现一些东西。
    如果你一边单步执行,一边打开SQL Server的SQL Profiler进行监控(监控的Event为Stored Procedures中的RPC:Completed),可以发现,在两个session.Save()方法以及session.Get<>()方法处,并没有产生任何跟数据库进行交互的SQL语句,而只有在trans.Commit()的时候,才会产生下面这样两条SQL:
exec  sp_executesql N ' INSERT INTO TBLCOMPANY (COMPANY_NAME, COMPANY_ID) VALUES (@p0, @p1) '
    N
' @p0 nvarchar(19),@p1 nvarchar(4) '
    
@p0   =  N ' BenQ Guru Co., Ltd. ' @p1   =  N ' 1000 '
exec  sp_executesql N ' INSERT INTO TBLCOMPANY (COMPANY_NAME, COMPANY_ID) VALUES (@p0, @p1) '
    N
' @p0 nvarchar(14),@p1 nvarchar(4) '
    
@p0   =  N ' test company 2 ' @p1   =  N ' 2000 '
    这是因为NHibernate在同一个session内会做对象的状态管理和缓存,对对象属性的修改被缓存起来,直到事务提交的时刻才将所有数据库更新操作应用到数据库上;在session.Get()获取对象时,先从当前session的缓存中查找是否已经存在该对象,如果有,则直接取出这个对象,而不会产生一条SQL查询。所以上面的测试只有两个INSERT语句。
    在上面测试的基础上,运行如下的测试代码
ISessionFactory sessionFactory  =   new  Configuration().Configure().BuildSessionFactory();
ISession session 
=   null , session2 = null ;
ITransaction trans 
=   null ;
try
{
    session 
=  sessionFactory.OpenSession();
    session2 
=  sessionFactory.OpenSession();
    trans 
=  session.BeginTransaction();

    Company company 
=  session.Get < Company > ( " 2000 " );
    company.CompanyName 
=   " My Test Company ... " ;
    Company company2 
=  session2.Get < Company > ( " 2000 " );

    session.Update(company);

    trans.Commit();
}
catch  (Exception e)
{
    trans.Rollback();
}
finally
{
    session.Close();
    session2.Close();
}
sessionFactory.Close();

Console.ReadLine();
    执行的SQL语句如下:
exec  sp_executesql 
    N
' SELECT company0_.COMPANY_ID as COMPANY1_0_0_, company0_.COMPANY_NAME as COMPANY2_0_0_ 
    FROM TBLCOMPANY company0_ WHERE company0_.COMPANY_ID=@p0
'
    N
' @p0 nvarchar(4) ' @p0   =  N ' 2000 '
exec  sp_executesql 
    N
' SELECT company0_.COMPANY_ID as COMPANY1_0_0_, company0_.COMPANY_NAME as COMPANY2_0_0_ 
    FROM TBLCOMPANY company0_ WHERE company0_.COMPANY_ID=@p0
'
    N
' @p0 nvarchar(4) ' @p0   =  N ' 2000 '
exec  sp_executesql N ' UPDATE TBLCOMPANY SET COMPANY_NAME = @p0 WHERE COMPANY_ID = @p1 '
    N
' @p0 nvarchar(19),@p1 nvarchar(4) ' @p0   =  N ' My Test Company ... ' @p1   =  N ' 2000 '
    其中第1、2句分别在session.Get()和session2.Get()调用时产生,因为这是两个不同的session,并且缓存中都还没有要取的company对象。第3句是在trans.Commit()时产生的。
    另外一点需要注意,NHibernate不允许修改主键值,如果有修改,在事务提交时会丢出一个异常。这个特性在使用业务上有意义的字段作为主键时可能会面临一些问题,不过从另一个方面看,就算这种情况下NH允许修改主键,因为其它对象可能已经根据这个主键值引用该对象,所以修改同样会造成问题。至少目前我接触的项目中,对象的业务主键是不允许修改的。

你可能感兴趣的:(NHibernate考察系列 02 使用入门 简单映射)