zoukankan      html  css  js  c++  java
  • 一、NHibernate 使用配置与实现简单查询

    NHibernate是从Hibernate迁移到DotNet来的优秀的ORM框架,它把数据库中的表的关系模型转换为程序中的对象之间的关联模型,从而使程序模型更接近于现实中的逻辑。作为DotNet本身在VS2008 SP1中新增了ADO.NET Entity Framework,但EF非常庞大,远超过ORM的概念范畴,使初学者难以把握。而在VS2005中却没有这种ORM框架,在此我们先以NHibernate为工具研究ORM思想,并研究它如何在VS2005中应用。
    ORM就是“对象-映射-关系”的简称,它主要包含三部分:
        关系:关系型数据库。
        对象:实体对象类
        映射:XML文件,指定实体类与表的对应关系。

    在这里需要我们操作的就有两点:编写实体对象类,配置映射文件。这两部份一般不需要我们手动编写,我们可以使用CodeSmith的模板来生成。

    一、R-关系部份
    以下面的数据库为例:
    create database mydb
    go
    use mydb
    go
    --水果表
    create table Fruit
    (
    Ids varchar(50) primary key,
    [Name] varchar(50) not null,
    Price decimal(8,2),
    Source varchar(50),
    Stack varchar(50),
    Numbers int, --库存数量
    [Image] varchar(50)
    )
    go
    insert into fruit values('k001','苹果',2.4,'烟台','2',100,'image/0.gif')
    insert into fruit values('k002','菠萝',1.4,'广东','3',100,'image/1.gif')
    insert into fruit values('k003','桔子',2.4,'福州','3',100,'image/2.gif')
    insert into fruit values('k004','葡萄',2.4,'新缰','2',100,'image/3.gif')
    insert into fruit values('k005','樱桃',2.4,'青岛','4',100,'image/4.gif')
    insert into fruit values('k006','桃子',2.4,'花果山','5',100,'image/5.gif')
    insert into fruit values('k007','香蕉',2.4,'济南','5',100,'image/6.gif')

    Fruit表是一个独立的单一表,我们以此表为例,研究如何配置ORM框架,并实现增、删、改、查功能

    二、O-对象部份
    第一步:新建一个类库Common
    第二步:向Common项目中添加NHibernate.dll引用
    第三步:使用CodeSmith执行NHibernate.cst文件生成实体类和映射文件
    《图1》
    Fruit.cs的文件代码如下:
    using System;
    using System.Collections;
    using System.Web.UI.WebControls;

    使用配置与实现简单查询" alt="一、NHibernate 使用配置与实现简单查询" src="http://hiphotos.baidu.com/grayworm/pic/item/3be3a1f8273c4211d8f9fd52.jpg" border=0 SMALL="0">

     

    namespace Common
    {

    public class Fruit : System.IComparable
    {
         //成员变量
       protected string _id;
       protected string _name;
       protected decimal _price;
       protected string _source;
       protected string _stack;
       protected int _numbers;
       protected string _image;
       protected static String _sortexpression_r = "Id";
       protected static SortDirection _sortDirection = SortDirection.Ascending;

            //构造函数
       public Fruit() { }

       public Fruit( string name, decimal price, string source, string stack, int numbers, string image )
       {
        this._name = name;
        this._price = price;
        this._source = source;
        this._stack = stack;
        this._numbers = numbers;
        this._image = image;
       }
      
       //属性
       public virtual string Id
       {
        get {return _id;}
        set
        {
         if ( value != null && value.Length > 50)
          throw new ArgumentOutOfRangeException("Invalid value for Id", value, value.ToString());
         _id = value;
        }
       }

       public virtual string Name
       {
        get { return _name; }
        set
        {
         if ( value != null && value.Length > 50)
          throw new ArgumentOutOfRangeException("Invalid value for Name", value, value.ToString());
         _name = value;
        }
       }

       public virtual decimal Price
       {
        get { return _price; }
        set { _price = value; }
       }

       public virtual string Source
       {
        get { return _source; }
        set
        {
         if ( value != null && value.Length > 50)
          throw new ArgumentOutOfRangeException("Invalid value for Source", value, value.ToString());
         _source = value;
        }
       }

       public virtual string Stack
       {
        get { return _stack; }
        set
        {
         if ( value != null && value.Length > 50)
          throw new ArgumentOutOfRangeException("Invalid value for Stack", value, value.ToString());
         _stack = value;
        }
       }

       public virtual int Numbers
       {
        get { return _numbers; }
        set { _numbers = value; }
       }

       public virtual string Image
       {
        get { return _image; }
        set
        {
         if ( value != null && value.Length > 50)
          throw new ArgumentOutOfRangeException("Invalid value for Image", value, value.ToString());
         _image = value;
        }
       }

            public static String Sortexpression_r
            {
                get { return _sortexpression_r; }
                set { _sortexpression_r = value; }
            }

            public static SortDirection SortDirection
            {
                get { return _sortDirection; }
                set { _sortDirection = value; }
            }
      
            //实现IComparable接口的排序方法
            public virtual int CompareTo(object obj)
            {
        if (!(obj is Fruit))
         throw new InvalidCastException("This object is not of type Fruit");
       
        int relativue;
        switch (Sortexpression_r)
        {
         case "Id":
          relativue = this.Id.CompareTo(((Fruit)obj).Id);
          break;
         case "Name":
          relativue = this.Name.CompareTo(((Fruit)obj).Name);
          break;
         case "Price":
          relativue = (this.Price != null) ? this.Price.CompareTo(((Fruit)obj).Price) : -1;
          break;
         case "Source":
          relativue = (this.Source != null) ? this.Source.CompareTo(((Fruit)obj).Source) : -1;
          break;
         case "Stack":
          relativue = (this.Stack != null) ? this.Stack.CompareTo(((Fruit)obj).Stack) : -1;
          break;
         case "Numbers":
          relativue = (this.Numbers != null) ? this.Numbers.CompareTo(((Fruit)obj).Numbers) : -1;
          break;
         case "Image":
          relativue = (this.Image != null) ? this.Image.CompareTo(((Fruit)obj).Image) : -1;
          break;
                    default:
                        goto case "Id";
        }
                if (Fruit.SortDirection == SortDirection.Ascending)
         relativue *= -1;
        return relativue;
       }
    }
    }

    三、M-映射部分
    Fruit.hbm.xml映射文件如下(在这里我用的是nhibernate2.2):
    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
        <!--Common.Fruit类与Fruit表进行映射-->
    <class name="Common.Fruit, Common" table="Fruit">
         <!--主键Id映射到Ids列-->
       <id name="Id" type="String" unsaved-value="null">
        <column name="Ids" length="50" sql-type="varchar" not-null="true" unique="true" index="PK__Fruit__7C8480AE"/>
       <generator class="native" />
       </id>
       <!--列映射-->
       <property name="Name" type="String">
        <column name="Name" length="50" sql-type="varchar" not-null="true"/>
       </property>
       <property name="Price" type="Decimal">
        <column name="Price" length="5" sql-type="decimal" not-null="false"/>
       </property>
       <property name="Source" type="String">
        <column name="Source" length="50" sql-type="varchar" not-null="false"/>
       </property>
       <property name="Stack" type="String">
        <column name="Stack" length="50" sql-type="varchar" not-null="false"/>
       </property>
       <property name="Numbers" type="Int32">
        <column name="Numbers" length="4" sql-type="int" not-null="false"/>
       </property>
       <property name="Image" type="String">
        <column name="Image" length="50" sql-type="varchar" not-null="false"/>
       </property>
    </class>
    </hibernate-mapping>
    第四步:把Fruit.hbm.xml文件作为嵌入资源,否则找不到该文件,就无法识别我们的实体对象类。

    到此为至,我们的O、R、M三部份都实现完成了,下面的内容就是配置NHibernate引擎。
    第五步:编写hibernate.cfg.xml配置文件,并把该文件入在网站的BIN文件夹中,否则也会找不到该文件。

    四、NHibernate的配置部份
    <?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">
                server=.;database=mydb;uid=sa;pwd=123;
            </property>
            <property name="adonet.batch_size">10</property>
            <property name="show_sql">true</property>
            <property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
            <property name="use_outer_join">true</property>
            <property name="command_timeout">10</property>
            <property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property>
            <mapping assembly="Common"/>
        </session-factory>
    </hibernate-configuration>
    hibernate.cfg.xml中配置了NHibernate的数据库链接,Sql方言相关信息。

    到目前为止所有的配置信息都已完成,剩下的内容就是编写代码访问数据库了。
    NHibernate访问数据库常用的有两个接口:ISessionFactory和ISession。
    ISessionFactory接口:负责初始化NHibernate。它充当数据存储源的代理,并负责创建Session对象。这里用到了工厂模式。一般情况下,一个项目通常只需要一个SessionFactory就够,当需要操作多个数据库时,可以为每个数据库指定一个SessionFactory。
    Session接口:负责执行被持久化对象的CRUD操作(增、删、改、查)。但ISession是非线程安全的。NHibernate的ISession不同于HTTP应用中的HttpSession,我们将HttpSesion对象称为用户session。

    五、使用NHibernate访问数据库
    第六步:在Common项目中建立SessionManager类
    using System;
    using System.Collections.Generic;
    using System.Text;
    using NHibernate;
    using NHibernate.Cfg;
    namespace Common
    {
        public class SessionManager
        {
            private ISessionFactory _SessionFactory;
            private ISession _Session;
            public SessionManager()
            {
                //生成SessionFactory
                _SessionFactory = new Configuration().Configure().BuildSessionFactory();
                //使用SessionFactory对象生成Session对象
                _Session = _SessionFactory.OpenSession();
            }
            //返回Session对象
            public ISession Session
            {
                get
                {
                    return _Session;
                }
            }
        }
    }
    该类的作用就是生成Session对象,以便对数据库的操作。

    第七步:创建数据库访问代码
    using System;
    using System.Collections.Generic;
    using System.Text;
    using NHibernate;

    namespace Common
    {
        public class FruitDA
        {
            private ISession _Session;
            public FruitDA()
            {
                //生成ISession对象
                _Session = new SessionManager().Session;
            }
            public IList<Fruit> Select()
            {
                //使用ISession对象的CreateQuery()方法来执行HQL查询数据库,并返回泛型集合数据
                IList<Fruit> list = _Session.CreateQuery("from Fruit").List<Fruit>();
                return list;
            }
        }
    }

    第八步:页面调用FruitDA类的Select()方法查询数据,并显示在页面上
    GridView1.DataSource = new FruitDA().Select();
    GridView1.DataBind();

    好了,使用NHibernate建立一个简单查询就完成了。

    NHibernate与ADO.NET访问数据库
    NHibernate只需要我们编写好实体类和映射文件就可以了,当然这部份代码我们可以使用CodeSmith来生成,一旦配置好NHibernate后,所以的数据库访问都由NHibernate代我们完成。作为开发人员,我们只需要理清商业逻辑,管理好我们的实体对象就可以了,不用再使用SqlConnection,SqlCommand等对象去为每个表编写枯燥数据库操作类了。

    NHibernate与Linq To Sql
    从易用性上来讲,NHibernate确实不如Linq To Sql容易使用,在实体类的生成和映射文件的生成中Linq To Sql只需要点点鼠标就可以实现了。但Linq To Sql是在VS2008中提供出来的,在VS2005中无法使用的。另外,对数据量不太大的情况下,Linq To Sql的性能不如NHibernate高,在数据量大的情况下,Linq To Sql则表现出强悍的性能。另外Linq To Sql目前只适用于SqlServer数据库,还不能算是一个完善的ORM框架。

  • 相关阅读:
    LightOJ1002 分类: 比赛 最短路 2015-08-08 15:57 15人阅读 评论(0) 收藏
    DZY Loves Chemistry 分类: CF 比赛 图论 2015-08-08 15:51 3人阅读 评论(0) 收藏
    周赛-DZY Loves Chessboard 分类: 比赛 搜索 2015-08-08 15:48 4人阅读 评论(0) 收藏
    周赛-Equidistant String 分类: 比赛 2015-08-08 15:44 6人阅读 评论(0) 收藏
    周赛-Toy Cars 分类: 比赛 2015-08-08 15:41 5人阅读 评论(0) 收藏
    A Knight's Journey 分类: POJ 搜索 2015-08-08 07:32 2人阅读 评论(0) 收藏
    哈希-4 Values whose Sum is 0 分类: POJ 哈希 2015-08-07 09:51 3人阅读 评论(0) 收藏
    哈希-Gold Balanced Lineup 分类: POJ 哈希 2015-08-07 09:04 2人阅读 评论(0) 收藏
    哈希-Snowflake Snow Snowflakes 分类: POJ 哈希 2015-08-06 20:53 2人阅读 评论(0) 收藏
    欧拉通路-Play on Words 分类: POJ 图论 2015-08-06 19:13 4人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/aaa6818162/p/2040303.html
Copyright © 2011-2022 走看看