前言
现代化大型项目通常使用独立的数据库来存储数据,其中以采用关系型数据库居多。用于开发项目的高级语言(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详解的详细内容...