NHibernate学习系列一
NHibernate是一个面向.NET环境的对象/关系数据库映射工具。对象/关系数据库映射(object/relational mapping,ORM)这个术语表示一种技术,用来把对象模型表示的对象映射到基于SQL的关系模型数据结构中去。
优点:
(1)NHibernate不仅仅管理.NET类到数据库表的映射(包括.NET 数据类型到SQL数据类型的映射),还提供数据查询和获取数据的方法,可以大幅度减少开发时人工使用SQL和ADO.NET处理数据的时间。
(2)面向对象:NHiberante的使用时只需要操纵对象,使开发更对象化,抛弃了数据库中心的思想,完全的面向对象思想。
(3)透明持久化:是他们正与(仅仅一个)Session相关联。一旦这个Session被关闭,这些对象就会脱离持久化状态,这样就可被应用程序的任何层自由使用。
缺点:
(1)内存消耗:直接使用“SqlHelper、DAL、BLL”无疑是最省内存的。使用NHibernate后,内存开销比较大,这点是毋庸置疑的。
(2)批量数据库的处理:由于NHibernate是基于面向对象的ORM框架,处理数据库的方式是针对单个对象的。对数据库的增、删、改都是正对一条记录而言。对于批量修改、删除数据,不适合用NHiberante。这也是所有OR框架弱点。
(3)表关系比较混乱时也不适合使用NHiberante。NHibernate只适合于表与表的关系比较明确的环境中。如本应该建立外键的,没有建立外键。这时使用NHiberante不仅没有减少工作量,反而增加了工作量。
使用NHiberante做一个简单实例:
(1)添加引用程序集:
(2)编写一个持久化类:
public class Classes { public Classes() { } #region Classes属性定义 private int _CID; /// <summary> /// 班级表ID /// </summary> public virtual int CID { get { return _CID; } set { _CID = value; } } private string _CName; /// <summary> /// 班级名称 /// </summary> public virtual string CName { get { return _CName; } set { _CName = value; } } private int _CCount; /// <summary> /// 班级人数 /// </summary> public virtual int CCount { get { return _CCount; } set { _CCount = value; } } private string _CImg; /// <summary> /// 班级Logo图片 /// </summary> public virtual string CImg { get { return _CImg; } set { _CImg = value; } } private bool _CIsDel; /// <summary> /// 删除标志 /// </summary> public virtual bool CIsDel { get { return _CIsDel; } set { _CIsDel = value; } } private DateTime _CAddTime; /// <summary> /// 录入时间 /// </summary> public virtual DateTime CAddTime { get { return _CAddTime; } set { _CAddTime = value; } } #endregion }
NHibernate对属性使用的类型不加任何限制。所有的.NET类型和原始类型(比如string,char和DateTime)都可以被映射,也包括.Net 集合(System.Collections)中的类。你可以把它们映射成为值,值集合,或者与其他实体类相关联。Id是一个特殊的属性,代表了这个类的数据库标识符(主键)。为了让上面提到运行时类增强功能生效,NHibernate持久化类的所有的public的属性必须声明为virtual。
(3)编写xml文件映射:xml文件必须以“类名.hbm.xml”格式命名;创建解决方案文件夹放入文件如下,则编写xml时就会有智能提示:
<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="HeiMaNH" assembly="HeiMaNH"> <class name="HeiMaNH.Classes,HeiMaNH" table="Classes"> <id name="CID" column="CID" type="Int32"> <generator class="identity" /> </id> <property name="CName" column="CName" type="String" length="50" /> <property name="CCount" column="CCount" type="Int32" length="4" /> <property name="CImg" column="CImg" type="String" length="40" /> <property name="CIsDel" column="CIsDel" type="Boolean" length="1" /> <property name="CAddTime" column="CAddTime" type="DateTime" length="8" /> </class> </hibernate-mapping>
(4)使用NHibernate的ISession(持久化管理器), 我们通过ISession来从数据库中存取数据
protected void Page_Load(object sender, EventArgs e) { //1.创建 会话 工厂(是可以被共享使用的, 是线程安全的) ISessionFactory factory = new Configuration().Configure().BuildSessionFactory(); //2.创建 会话(非共享使用,非线程安全,但是如果针对当前请求里的每个数据库操作都创建 会话,则极度浪费资源,所以,最好是 针对每次请求 只创建一个 会话) ISession sess = factory.OpenSession(); //HttpContext.Current.Items.Add("nfsession", sess); //3.创建查询对象 (hql-hibernate query language) IQuery query = sess.CreateQuery("from Classes c where c.CIsDel = false"); //3.2更加面向对象化的查询方式 //ICriteria crit = sess.CreateCriteria(typeof(Classes)); //crit.Add(Restrictions.Eq("CIsDel", false)); //crit.Add(Restrictions.Eq("CName", "刘德华2")); //IList<Classes> list = crit.List<Classes>(); //4.获得查询结果 IList<Classes> list = query.List<Classes>(); rptList.DataSource = list; rptList.DataBind(); }
对象状态:
数据库中没有数据与之对应,超过作用域会被垃圾回收.
其实 一般就是 new出来 且与 ISession没有关联的对象;
数据库中有数据与之对应,当前与ISession关联,并且相关联的isession也没有关闭,事物没有提交:持久对象状态发生改变,在事务提交时会影响到数据库(nhibernate能检测到改变);
数据库中有数据与之对应,但当前没有session与之关联;脱管对象状态发生改变,nhibernate不能检测到;
面向对象的查询语言,与SQL不同,HQL中的对象名是区分大小写的(除了C#类和属性其他部分不区分大小写);
HQL中查的是对象而不是表,并且支持多态;
HQL主要通过Query来操作,Query的创建方式:
IQuery q = sess.CreateQuery(hql);
from Person
from User u where u.name=:name
from User u where u.name=:name and u.birthday<:birthday
Criteria 是一种比HQL更面向对象的查询方式;
ICriteria crit = sess.CreateCriteria(typeof(User));
简单属性条件如:crit.Add(Restrictions.eq(proName,value));
crit.Add(Restrictions.eqProperty(proName,otherProName));
使用NHibernate进行关联映射