Nhibernate总结内容

    添加时间:2013-5-15 点击量:

    目  录


    1、有关Nhibernate 2


    2、nhibernate的景象设备 2


    2.1  Web.config设备文件 3


    2.2 添加Loglist.hbm.xml 4


    3、nhibernate代码 5


    3.1、根蒂根基的HQL语句 5


    3.2、插入和删除记录 6


    3.3、多前提查询 7


    3.4、将IList转换为DataTable函数 7


    4、常见异常及解决办法 8


    总结 9


     


    1、有关Nhibernate


    NHibernate 是一个面向.NET 景象的对象/关系数据库映射对象。对象关系映射(O/R Mapping,Object Relational Mapping)默示一种技巧,用来把对象模型默示的对象映射到基于SQL 的关系模型数据布局中去。


    2、nhibernate的景象设备


    1NHibernate-2.1.2.GA-bin.zip和NHibernate-2.1.2.GA-src.zip


    2)新建名字为Nhibernate_map的Asp.net Web Application,导入nhibernate的相干引用,在NHibernate-2.1.2.GA-bin.zip文件夹下:


     


    3)创建数据库表t_sys_Log,同时在里新建一个对应的映射类Loglist.cs,即映射类和设备文件里的字段属性与数据库表里的字段属性是一一对应的,包含名称和类型;以类型为StringUserName为例,如下图所示:


    Ø 数据库表t_sys_Log:


     


    Ø t_sys_Log表的Nhibernate映射类Loglist:


     


    Ø t_sys_Log数据表所对应的设备文件


     


    重视:


    数据库的存放地位,跟映射无关。映射的形成首要因为映射类、映射文件.hbm.xml文件和config设备文件。在web中设备项直接放在web.config中;在WindowsFormsApplication中要添加App.config(具体:Add---AddItem—configuration file,默认名字为App.config)。设备文件的内容和功能是一样的。下面以文本.web.config为例:


    2.1  Web.config设备文件


    <section name=hibernate-configuration type=NHibernate.Cfg.ConfigurationSectionHandler,NHibernate/>


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


        <session-factory>


          <property name=connection.provider>


            NHibernate.Connection.DriverConnectionProvider


          </property>      


          <property name=dialect>


            NHibernate.Dialect.MsSql2005Dialect


          </property>


           <property name=connection.driver_class>


            NHibernate.Driver.SqlClientDriver


          </property>      


          <property name=connection.connection_string>


            Server=(local);Initial Catalog= csrcmap; 


            <!--User Id=123;Password=123456-->


            Integrated Security=True


          </property>      


          <property name=proxyfactory.factory_class>


            NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu


          </property>


          <property name=show_sql>true</property>


        </session-factory>


      </hibernate-configuration>


    该设备文件解析:


    Ø <section name=hibernate-configuration type=NHibernate.Cfg.ConfigurationSectionHandler,NHibernate/>


    该项添加到<configSections></configSections>之间;其余项目组添加到<configuration></configSections>内的随便率性地位


    Ø urn:nhibernate-configuration-2.2为nhibernate的版本号,在里的所有有关nhibernate的版本号必须一致,另一处在Loglist.hbm.xml里


    Ø NHibernate.Dialect.MsSql2005Dialect:为数据库操纵说话;本次应用的是sqlserver2005


    Ø connection.driver_class:为对应的数据库驱动


    Ø connection.connection_string:Server=(local);Initial Catalog= csrcmap:连接字符串;Server=127.0.0.1数据库办事器的IP地址;csrcmap为数据库的名字;Integrated Security=True如许的连接字符串是在数据库为windows验证登岸的景象下;不然,加上数据库sql登岸的用户名和登岸暗码:User Id=用户名;Password=暗码


    Ø proxyfactory.factory_class:nhibernate工厂,有三种:LinFu,castel等,选择哪一种要添加对应的引用


    Ø 设置copy to output Directory 属性为copy aways


    2.2 添加Loglist.hbm.xml


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


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


                        assembly=Nhibernate_map


                        namespace=Nhibernate_map> 


      <class name=Nhibernate_map. Loglist table= t_sys_Log  lazy=false>


        <id name=Id column=LogonId type=String length=20>


          <generator class=assigned />


        </id>


          <property name=UserName column= UserName type=String length=500/>


        <property name=Ip  type=String length=100/>


        <property name=Title  type=String length=500/>


        <property name=UserDateTime type=DateTime/>


        <property name=Memo  />  </class>


    </hibernate-mapping>


    重视事项:


    Ø 名字必须是映射类名.hbm.xml


    Ø Assembly和namespace对应的是映射类的定名空间的名字


    Ø class name为全称,即定名空间.类名;table为数据库对应的类名;lazy=false               是为了防止失足,具体什么感化不清楚


    Ø 下面是映射类的属性和数据库表的一一对应关系,包含名称和类型的对应


    Ø Loglist.hbm.xml的BuildAction属性设置为Embedded Resource


    3、Nhibernate跨数据库


    应用Nhibernate就是为了在不合数据库之间进行操纵时,不消批改太多的法度代码,只需更改设备文件即可。在进修过程中,实现了NhibernateSQLserver2000SQLserver2005Oracle 10之间的转换。


    3.1 SQLserver2000SQLserver2005


    Nhibernate持久层在SqLserver2000Sqlserver2005数据库之间,要批改的代码较少;首要有一处:在Web.config中有如许一处设备<property name=dialect>


                                               NHibernate.Dialect.MsSql2000Dialect


                                          </property>


    须要批改的只是将MsSql2000Dialect改为MsSql2005Dialect。其它的无需改变即可直接应用。


    3.2 SQLserverOracle 10 


    因为SQLserveroracle数据库自身存在的差别较大,当从SQLserver+Nhibernate转换为Oracle+Nhibernate时,须要批改的处所较多。


    起首要申明的一点:Oracle数据库和表、视图、字段名称全部为大写;这一点斗劲轻易受到困惑。其实如许不影响HQL操纵,因为在Nhibernate里面操纵的是映射类,跟具体的数据表或字段的名称没紧要,只需在创建映射类时一一对应即可。这一点在.hbm.xml文件中有所表现。


     


    第二,因为OracleSQLserver的驱动类等存在不合,Oracle+Nhibernateweb.config应批改设备为:


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


    <session-factory>


    <property name=connection.provider>


            NHibernate.Connection.DriverConnectionProvider


          </property>


          <property name=dialect>


            NHibernate.Dialect.Oracle10gDialect


          </property>


          <property name=connection.driver_class>


            NHibernate.Driver.OracleClientDriver


          </property>


          <!-- gepeipei 2011-6-6 办事器201上的数据库连接字符串-->


          <property name=connection.connection_string>


            Data Source=orcl201;User ID=nhb;Password=123456;Persist Security Info=true;Unicode=True


          </property>


          <!-- 连接Oracle -->


          <property name=query.substitutions>


            true 1, false 0, yes Y, no N


          </property>


          <property name=proxyfactory.factory_class>


            NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu


          </property>


          <property name=show_sql>true</property>


    </session-factory>


    </hibernate-configuration>


    第三、Oracle的数据类型;在SQLserver+Nhibernate时,可以很便利的将SQLserver的数据类型转换为HQL中的数据类型。但在Oracle+Nhibernate中,数据转换存在一些题目。所涉及到的一些数据类型中,最轻易失足的是DataTime类型和System.Guid类型。


    下面以这两个为例进行具体的申明:


    起首DataTime类型,因为Nhibernate和Oracle内嵌的日期格局不一样,在直接进行应用时,一般会报错。更正这个题目的办法是在DataTime日期对象前面加上TO_DATE()进行转换,且TO_DATE必然要大写,Oracle严格区分大小写,小写时同样报错。例如在HQL语句中呈现:USERDATETIME>= UserDateTimeBegin时,应将其改为 USERDATETIME >=TO_DATE( + UserDateTimeBegin + ,YYYY-MM-DD)。同时,在批改法度代码时发明“Order by USERDATETIME ”在HQL中底子不起感化,获得的列表为乱序。 


    SQLserver和HQL中都存在System.Guid类型或是与其对应的类型,可以直接彼此转换不失足。然则在Oracle数据库中没有直接可用的对应数据类型,网上一般推荐应用RAW类型或CHAR类型。RAW(16)可以跟Guid类型对应,然则数据库表里的值侍从跟从数据库表里读出来显示到网页上的值不一样,在本次日记移植测试时,应用的VCHAR(50);也因为所应用的Oracle是从SQLserver2000数据库中转换而来的,在转换过程中也会报错,是以选择了VCHAR类型,即对应HQL里的String类型。就是将Guid类型转换为string字符串类型,传到数据库表中,再将其读出,即可获得一致的数值。如许在应用时也会呈现一些题目,但根蒂根基是可用的,须要改进。


    4、MyGeneration的简单应用


    4.1 MyGeneration代动生成器


    MyGeneration 是一款不错的ORM和代码生成对象,它基于模板(Template)工作,安装好MyGeneration 后自带了很多模板,并且供给在线模板库供给模板进级和容许用户自定义模板。MyGeneration 的模板可以用C#, VB.NET, JScript, and VBScript编写。应用MyGeneration 可认为Gentle.NET, Opf3, NHibernate等生成ORM架构或ORM文件,为多种数据库生成活生计储过程,为.Net项陌生成C#VB.NET 法度代码,PHPHTML等页面代码。


    本次应用MyGeneration主如果主动生成映射类和对应的.hbm.xml文件;希罕是在数据库类较多的景象下,应用这款代码生成对象,可以大大的进步效力。简单应用步调图示如下:


    Ø 创建不合数据库的连接:


     


    Ø 打开Template Browser和在线模板库


     


    Ø 在线模板库里找到Nhibernate1.4,并将其


     


    Ø 在Template Browser里找到Nhibernate1.4,右键履行


     


    Ø 选择对应的数据库表或视图进行Map操纵


     


     


    Ø 在MyGeneration的安装目次下,有个名为GeneratedCode的文件夹,主动生成的映射实体类存放于该处


     


    Ø 题目:在对视图进行Map时,只生成实体类,没有映射.hbm.xml文件,须要进一步研究


    5、Nhibernate+增删改查


    5.1、根蒂根基的HQL语句


    Ø  Loglist order by UserDateTime DESC


    等价于SQL里:   LogList order by UserDateTime DESC


    Ø   Loglist where ID = id


    等价于 :  LogList where ID=id


    Ø  Loglist where ID = id


    Ø  avg(c.CustomerId),sum(c.CustomerId),count(c)  Customer c


    Ø Or语句


    IList list = (IList)session.CreateCriteria(typeof(Loglist))


    .Add


          (


          NHibernate.Criterion.Restrictions.Or


             (


                  NHibernate.Criterion.Restrictions.Like(Title, % + Memo + %),


                   NHibernate.Criterion.Restrictions.Like(Memo, % + Memo + %)


                 )


            )


        .AddOrder(Order.Desc(UserDateTime))


    .List<Loglist>() as IList;


    重视:所有的HQL操纵的都是映射类,不是数据库表,上方的Loglist是映射类名,不是数据库表的名称。HQL语句严格区分大小写。


    5.2、Nhibernate的根蒂根基功能操纵


    Nhibernate在履行时操纵的是类的对象,鄙人文应用到的代码均为从oracle+Nhibernate里拷贝过来的,所以会有大小写的不合:


    插入时,即插入一个对象;是以要先新建一个对象,对对象的各个属性字段进行赋值;然后保存session


    代码:


    //gepeipei 2011-5-23


                T_SYS_LOG log = new T_SYS_LOG();


                 log.ID = id;


                 log.IP = Ip;


                 log.USERNAME = UserName;


                 log.TITLE = Title;


                 log.MEMO = content;


                 log.USERDATETIME = DateTime.Now;


                //gepeipei 2011-5-26


             session.Save(log);


             sessionFlush()


             tran.Commit();


    删除时;可以对一个对象进行直接删除,即session.(对象);也可以履行HQL语句,如: 字段名  表名 where 字段=“”;履行完HQL语句之后,要进行session更新操纵,不然数据库表的数据不变。


    法一:


    //获取一个合适前提的T_SYS_DATA对象


    T_SYS_DATA dt = data.GetModel(ID);


                session.Delete(dt);


                session.Flush();


            tran.Commit();


    法二:


    string str_sql = ;


                //NHibernate语句 gepeipei 2011-5-23


                str_sql =    T_SYS_LOG ;


                str_sql +=  WHERE ID =  + ID +  ;


                //履行sql语句,在进行删除操纵时,须要履行更新操纵,不然删除成果不受影响


                    IQuery query = session.CreateQuery(str_sql);


                int row = query.uteUpdate();


    批改时:在证监会里用到了编辑操纵和用户暗码批改,这两个都属于对数据库对象的批改。在这里没有应用更新语句,而是按照给出的前提获取一个新的对象,像按照ID,获得一个T_SYS_DATA的对象,在对于这个对象的项目组属性进行批改;最后以              session.Saveor()


    session.Flush();


    Tran.Commit(),进行更新。


    代码:


    T_SYS_DATA data = data_1.GetModel(ID);


                    data.DAC = DataMc;


                    data.DISPLAYORDER = DisplayOrder;


                    data.ISUSE = IsUse;


                    data.ISVISIBLE = IsVisible;


                    session.SaveOrUpdate(data);               


                    session.Flush();


                tran.Commit();


    查询时:相对斗劲简单,HQL语句跟sqlserver语句根蒂根基一致,就是在oracle里要把表名和属性字段改为大写。履行lqy= session.CreateQuery(Sqlstr);将查询成果赋值给list,就可以将其取出应用


    5.3、多前提查询


    HQL多前提查询时,支撑Or、And等连接的HQL语句,失足概率也斗劲大,是以推荐应用较正规点的ICriteria进行多前提的查询


    哄骗ICriteria进行前提查询;session.CreateCriteria(typeof(Loglist)


    //Ge,Le,Eq对应于大于小于便是;返回值为IList类型, 


    list_log = (IList )session.CreateCriteria(typeof(Loglist))


                 .Add(Restrictions.Ge(UserDateTime, Convert.ToDateTime(UserDateTimeBegin)))


                 .Add(Restrictions.Le(UserDateTime, Convert.ToDateTime(UserDateTimeEnd)))


                 .SetFirstResult(AspNetPager1.PageSize  (AspNetPager1.CurrentPageIndex - 1))//从哪笔记录开端


                 .SetMaxResults(AspNetPager1.PageSize)//统共几许笔记录


                 .AddOrder(Order.Desc(UserDateTime))


                 .List<Loglist>();


    5.4、将IList转换为DataTable函数


    nhibernate里面最常用的就是IList类型,但Ilist类型有个毛病就是不排序,若是要进行数据绑定的话,须要将其转换为DataTable,再将其绑定


    public  DataTable ToDataTable(IList list)


    {


            DataTable result = new DataTable();


            if (list.Count > 0)


            {


                PropertyInfo[] propertys = list[0].GetType().GetProperties();


                foreach (PropertyInfo pi in propertys)


                {


                    result.Columns.Add(pi.Name, pi.PropertyType);


                }


                for (int i = 0; i < list.Count; i++)


                {


                    ArrayList tempList = new ArrayList();


                    foreach (PropertyInfo pi in propertys)


                    {


                        object obj = pi.GetValue(list[i], null);


                        tempList.Add(obj);


                    }


                    object[] array = tempList.ToArray();


                    result.LoadDataRow(array, true);


                }


            }


            return result;


    }


    6、常见异常及解决办法


    Ø not mapped


    失足点:有可能是hql语句操纵的不是映射类的名字,而是表的名字;


            或者是.hbm.xml文件的buildaction没有设置为embedded resource


    Ø 未能从法度集“Nhibernate_map, Version=1.0.0.0, Culture=neutral,  PublicKeyToken=null”中加载类型“Nhibernate_map.11”


            cfg.AddAssembly(Nhibernate_map);报错


           失足点:.hbm.xml文件中的class name所对应的值不是映射类的全称,或者是名字不合错误


    Ø Could not find schema information for the element urn:nhibernate-mapping-2.0:hibernate-mapping


    失足点:版本号不合错误,或者是两个文件中的版本号不一致(web.config.hbm.xml


    Ø Could not find the dialect in the configuration异常


    失足点:config文件中有关数据库驱动和数据库说话设备跟所应用的数据库不一致引起的


    Ø 提示添加<property name=proxyfactory.factory_class>        NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu  </property>


          <property name=proxyfactory.factory_class>


            NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle  </property>的异常


           失足点:引用不全,添加LinFu或Castle 的引用,这是两种工厂创建体式格式,选其一即可,添加对应的引用


    Ø 激发类型为“Antlr.Runtime.NoViableAltException”的异常。


            失足点:HQL语句呈现语法错误


    总结


    有关nhibernate应用过程中,大项目组失足源于设备文件的设置(版本号、数据库名和映射类名,嵌入资料),及映射类和数据库表Mapping关系,还有就是要记住nhibernate里的HQL语句操纵的是映射类的对象,不是数据库表,这是首要的差别,因为操纵的是映射类,所所以面向对象的,离开了纯真的数据库表的操纵,供给了一个.net和数据库之间的部件,不合的数据库只要数据设备文件里设置的驱动不合即可实现连接和映射。


    分享到: