好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

在C#项目中如何使用NHibernate详解

前言

现代化大型项目通常使用独立的数据库来存储数据,其中以采用关系型数据库居多。用于开发项目的高级语言(c#、java等)是面向对象的,而关系型数据库是基于关系的,两者之间的沟通需要一种转换,也就是对象/关系数据库映射(object/relational mapping,简称orm)。

c#可用以解决对象/关系数据库映射的工具有多种,常见的有ef (entity framework)、nhibernate、ibatis等,各自的优缺点及适用场景在此不做讨论,本文只对如何使用nhibernate做个总结。

nhibernate是一个面向.net环境的对象/关系数据库映射工具。

1. 创建项目文件

在visual studio开发工具里创建需要的项目结构。

2. 添加对nhibernate的引用

当下载并解压nhibernate安装包后,电脑上就会创建一些目录,包括[required_bins],要把 required_bins目录下的dll引用到项目里来,它们是nhibernate使用的核心组件。

nhibernate.dll(基础类库,与数据库直接打交道,位于数据访问层)

iesi.collections(基础类库辅助类库,位于数据访问层)

antlr3.runtime(基础类库辅助类库,位于数据访问层)

nhibernate.bytecode.spring.dll(proxy factory类库,用于打开/关闭nhibernate session,位于数据访问层工具类库)

 

 图1 添加对nhibernate的引用

3. 配置nhibernate

文件:hibernate.cfg.xml,位于站点根目录。

?

<? xml version = "1.0" encoding = "utf-8" ?>

< hibernate-configuration xmlns = "urn:nhibernate-configuration-2.2" >

  < session-factory >

  < property name = "connection.driver_class" >nhibernate.driver.sqlclientdriver</ property >

  < property name = "connection.connection_string" >

  data source=120.120.200.200;initial catalog=mamall;persist security info=true;user id=mamall;password=mima123;connection reset=false;connection lifetime=50;min pool size=1;max pool size=500

  </ property >

  < property name = "adonet.batch_size" >10</ property >

  < property name = "show_sql" >true</ property >

  < property name = "dialect" >nhibernate.dialect.mssql2005dialect</ property >

  < property name = "command_timeout" >10</ property >

  < property name = "query.substitutions" >true 1, false 0, yes 'y', no 'n'</ property >

  < property name = "proxyfactory.factory_class" > nhibernate.bytecode.spring.proxyfactoryfactory,nhibernate.bytecode.spring</ property >

  < property name = "connection.release_mode" >on_close</ property >

  < mapping assembly = "fuli.entity" />

  </ session-factory >

</ hibernate-configuration >

4. 编写nhibernatehelper辅助类

文件:nhibernatehelper.cs

?

using system;

using fuli.tool.log;

using nhibernate;

using nhibernate.cfg;

namespace fuli.dal.common

{

  public class nhibernatehelper

  {

  private static isessionfactory _sessionfactory;

  private static isessionfactory sessionfactory

  {

   get

   {

   if (_sessionfactory == null )

   {

    var configuration = new configuration();

    configuration.configure();

    _sessionfactory = configuration.buildsessionfactory();

   }

   return _sessionfactory;

   }

  }

 

  public static isession opensession()

  {

   try

   {

   return sessionfactory.opensession();

   }

   catch (exception ex)

   {

   loghelper.getinstance().writemessage( "打开数据库失败,错误:" + ex.tostring());

   return null ;

   }

  }

  }

}

5. 创建数据模型

nhibernate允许直接使用plain old clr objects (pocos),而不用通过存储过程来直接和数据库交互。使用pocos的一个优势在于不用绑定特定的持久化层。相比较而言,有些orm解决方案需要特殊属性,或者是基于模型对象,这些对象又是从特定的基类中继承而来的。

在nhibernate中不用特殊的修饰就可以让对象和持久化层交互。要注意的是所有需要持久化的属性必须是虚拟的,并且要开启延迟加载,所有数据模型类中的公共方法必须是虚拟的,哪怕它们并没有包含到映射文件中。

通常来讲,最好把所有的属性都设置为虚拟的。

可以借助mygeneration自动代码工具从数据表生成数据模型和对应的映射文件。

?

using system;

using system.collections.generic;

 

namespace fuli.entity.domain

{

  /// <summary>

  /// 共享编码表(字典表)

  /// </summary>

  [serializable]

  public class sharedcode

  {

  #region 构造方法

 

  public sharedcode()

  {

   m_id = 0;

   m_category = string .empty;

   m_text = string .empty;

   m_value = string .empty;

   m_isdefault = false ;

   m_description = string .empty;

   m_parentid = 0;

   m_sortorder = 0;

  }

 

  #endregion 构造方法

 

  #region 私有变量

 

  private long m_id;

  private string m_category;

  private string m_text;

  private string m_value;

  private bool m_isdefault;

  private string m_description;

  private long m_parentid;

  private short m_sortorder;

 

  #endregion 私有变量

 

  #region 公有属性

 

  ///<summary>

  /// 主键id

  ///</summary>

  public virtual long id

  {

   get { return m_id; }

   set { m_id = value; }

  }

 

  ///<summary>

  /// 分类

  ///</summary>

  public virtual string category

  {

   get { return m_category; }

   set { m_category = value; }

  }

 

  ///<summary>

  /// 文本

  ///</summary>

  public virtual string text

  {

   get { return m_text; }

   set { m_text = value; }

  }

 

  ///<summary>

  /// 编码值

  ///</summary>

  public virtual string value

  {

   get { return m_value; }

   set { m_value = value; }

  }

 

  ///<summary>

  /// 是否是同类里默认

  ///</summary>

  public virtual bool isdefault

  {

   get { return m_isdefault; }

   set { m_isdefault = value; }

  }

 

  ///<summary>

  /// 描述

  ///</summary>

  public virtual string description

  {

   get { return m_description; }

   set { m_description = value; }

  }

 

  ///<summary>

  /// 父级id(如果有)

  ///</summary>

  public virtual long parentid

  {

   get { return m_parentid; }

   set { m_parentid = value; }

  }

 

  ///<summary>

  /// 排列次序

  ///</summary>

  public virtual short sortorder

  {

   get { return m_sortorder; }

   set { m_sortorder = value; }

  }

 

  #endregion 公有属性

 

  #region 扩展属性

 

  #endregion 扩展属性

 

  #region rewrite equals and hashcode

 

  /// <summary>

  ///

  /// </summary>

  public override bool equals( object obj)

  {

   if ( this == obj) return true ;

   if ((obj == null ) || (obj.gettype() != gettype())) return false ;

   sharedcode castobj = (sharedcode)obj;

   return (castobj != null ) && (m_id == castobj.id);

  }

 

  /// <summary>

  /// 用唯一值实现gethashcode

  /// </summary>

  public override int gethashcode()

  {

   int hash = 57;

   hash = 27 * hash * m_id.gethashcode();

   return hash;

  }

 

  #endregion rewrite equals and hashcode

  }

}

6. 创建nhibernate映射文件

nhibernate使用xml映射文件来映射poco到数据库对象。虽然在很多案例中这可能是一对一关系,但这并不是必定的。

文件:sharedcode.hbm.xml

?

<? xml version = "1.0" encoding = "utf-8" ?>

< hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" >

  < class name = "fuli.entity.domain.sharedcode, fuli.entity" table = "sharedcode" >

   < id name = "id" column = "id" type = "int64" unsaved-value = "0" >

    < generator class = "native" />

   </ id >

   < property name = "category" type = "string" column = "category" />

   < property name = "text" type = "string" column = "text" />

   < property name = "value" type = "string" column = "value" />

   < property name = "isdefault" type = "boolean" column = "isdefault" />

   < property name = "description" type = "string" column = "description" />

   < property name = "parentid" type = "int64" column = "parentid" />

   < property name = "sortorder" type = "int16" column = "sortorder" />

  </ class >

</ hibernate-mapping >

在hibernate-maping标签中,同时引用类集(pocos)所属的程序集命名空间。

class元素表示到单个poco的映射。name表示上面的程序集和命名空间中的类名,table属性告诉nhibernate数据库中的哪个表或者视图将被映射。 id元素告诉nhibernate哪个数据库的字段和对应的对象作为一个唯一键来使用。在本例中,我们使用id这个字段。 generator元素告诉nhibernate怎样给新实体来创建唯一id。 property标签是见得最多的标签。它简单地映射一个到数据表或者视图中对应字段的映射。

一旦xml文件创建好了,需要更改xml的生成方式确保它被设置为嵌入式资源,否则nhibernate不会读取这个xml文件,那么映射就不会生效了。

 

图2 映射文件必须是嵌入的资源

7. 使用 nhibernate连接数据库

文件:commonrepository

?

namespace fuli.dal.sqlserverimpl

{

  public class commonrepository : icommonrepository

  {

   #region 新增

   /// <summary>

   /// 新增实体表

   /// </summary>

   /// <param name="obj"></param>

   /// <returns></returns>

   public long addnewentity<t>( object obj, string tablename) where t : new ()

   {

    long id = 0;

    try

    {

     using (isession session = nhibernatehelper.opensession())

     {

      id = long .parse(session.save((t)obj).tostring());

      session.flush();

     }

    }

    catch (exception ex)

    {

     loghelper.getinstance().writemessage(tablename + operationtype.comma + ex.tostring());

    }

    return id;

   }

 

   /// <summary>

   /// 新增实体表

   /// </summary>

   /// <param name="entity"></param>

   /// <returns></returns>

   public treturn addnewentity<tentity, treturn>( object entity, string tablename) where tentity : new ()

   {

    treturn returnvalue = default (treturn);

    try

    {

     using (isession session = nhibernatehelper.opensession())

     {

      object returnobject = session.save(entity);

      if (returnobject != null )

      {

       returnvalue = (treturn)convert.changetype(returnobject, typeof (treturn));

      }

      session.flush();

     }

    }

    catch (exception ex)

    {

     loghelper.getinstance().writemessage(tablename + operationtype.comma + ex.tostring());

    }

    return returnvalue;

   }

   #endregion 新增

  }

}

对于不同的实体,可以一对一地写一个<entity>repository,专注负责相对应的实体操作。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。

原文链接:http://www.cnblogs.com/ywqu/p/8664360.html

dy("nrwz");

查看更多关于在C#项目中如何使用NHibernate详解的详细内容...

  阅读:47次