• 我的第一个NHibernate程序


    休息两天半.打开博客园看到NHibernate专题.比较迷茫,俺可是ORM是什么都不知道的那种菜鸟.

    本篇基本上是从菜鸟的角度构建的一个NHibernate的QuickStart:将一条数据写入数据库.

    参看:李永京 NHibernate之旅系列第二篇和http://www.cnblogs.com/kiler的NHibernate2.0文档的非官方汉化版本.

    李老人家的版本比较高深,一直不成功.太大了,感觉不是和我这样的菜菜.于是又参看http://www.cnblogs.com/kiler汉化的NHibernate2.0文档.

    有那么个意思,挺好懂的!不过NHibernate2.0文档上的配置不全,运行时会报

    The ProxyFactoryFactory was not configured.

    ProxyFactoryFactory 没有设置!

    下变是我构建第一个NHibernate的过程:

    下载:https://sourceforge.net/projects/nhibernate/files/

    我用的是最新版3.0Alpha2版,刚下的

    一、首先:数据库部分.

    在数据库中创建一个表Cat,创建脚本如下:

    CREATE TABLE [dbo].[Cat](
        [ID] [char](32) NOT NULL,
        [Name] [nvarchar](50) NULL,
        [Sex] [nchar](10) NULL,
        [Weight] [real] NULL,
    CONSTRAINT [PK_Cat] PRIMARY KEY CLUSTERED 
    (
        [ID] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY] 
    
    GO 

    创建一个用于实验的表.我没有用李老的表,那个表比较复杂,还要涉及到表间的关系什么的!

    二、创建一个WebApplication

    我没有用李老那种方法:创建一个类库,然后编写NUnit测试。我NUnit比较生,昨天晚上看代码才知道是干什么用的!在Cnblog上找了篇文章看了一晚上才理解NUnit的用法。为了省事,干脆,用WebApplication承载我的实验,所有东西都放到里边去!

    创建号这个WebApplication:NHibernateQuickStart

    之后添加对NHibernate.dll和NHibernate.ByteCode.Castle.dll的引用.

    三、配置Web.Config

    首先在web.config中添加一个配置元素

        <configSections>
            <section
                name="hibernate-configuration"
                type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate"
            />
        </configSections>
    设置一下:
    <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
            <session-factory>
                <property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
                <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
                <property name="connection.connection_string">
                    Server=(local);initial catalog=quickstart;Integrated Security=SSPI
                </property>
                <mapping assembly="QuickStart" />
            </session-factory>
        </hibernate-configuration>
    这里有几个属性没有设置,运行时会报错:

              The ProxyFactoryFactory was not configured.

    参看李老的:

    在这里加入了如下配置快:注册NHibernate.ByteCode.Castle.ProxyFactoryFactory

    <property name="adonet.batch_size">10</property>
          <property name="proxyfactory.factory_class">
            NHibernate.ByteCode.Castle.ProxyFactoryFactory,
            NHibernate.ByteCode.Castle
          </property>
    最终的Webconfig如下: 
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <!-- Add this element -->
        <configSections>
            <section
                name="hibernate-configuration"
                type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate"
            />
        </configSections>
    
        <!-- Add this element -->
        <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
            <session-factory>
                <property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
                <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
                <property name="connection.connection_string">
                    Server=(local);initial catalog=quickstart;Integrated Security=SSPI
                </property>
          <property name="proxyfactory.factory_class">
            NHibernate.ByteCode.Castle.ProxyFactoryFactory,
            NHibernate.ByteCode.Castle
          </property>
                <mapping assembly="QuickStart" />
            </session-factory>
        </hibernate-configuration>
     
        <!-- Leave the system.web section unchanged -->
        <system.web>
            ...
        </system.web>
    </configuration>
      
    四、添加一个持久化类

    NHibernate使用简单的.Net对象(Plain Old CLR Objects ,就是POCOs,有时候也称作Plain Ordinary CLR Objects)这种编程模型来进行持久化,POCO类通过set和get属性 访问其内部成员变量,对外则隐藏了内部实现的细节(假若需要的话,NHibernate也可以直接访问其内部成员变量)。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace NHibernateQuickStart
    {
        public class Cat
        {
            private string id;
            private string name;
            private char sex;
            private float weight;
    
            public Cat()
            {
            }
    
            public virtual string Id
            {
                get { return id; }
                set { id = value; }
            }
    
            public virtual string Name
            {
                get { return name; }
                set { name = value; }
            }
    
            public virtual char Sex
            {
                get { return sex; }
                set { sex = value; }
            }
    
            public virtual float Weight
            {
                get { return weight; }
                set { weight = value; }
            }
    
        }
    }
    
    NHibernate持久化类的所有的public的属性必须声明为virtual
     
    五、映射cat

    Cat.hbm.xml映射文件包含了对象/关系映射(O/R Mapping)所需的元数据。元数据包含持久化类的声明和属性到数据库的映射(指向字段和其他实体的外键关联)。

    请注意Cat.hbm.xml在Visual Stuido里面要设置为嵌入式资源(embedded resource),否则会报错。

    新建一个xml文件名字为Cat.hbm.xml,添加如下内容:
    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
        namespace="NHibernateQuickStart" assembly="NHibernateQuickStart">
    
      <class name="Cat" table="Cat">
    
        <!-- A 32 hex character is our surrogate key. It's automatically
                generated by NHibernate with the UUID pattern. -->
        <id name="Id">
          <column name="Id" sql-type="char(32)" not-null="true"/>
          <generator class="uuid.hex" />
        </id>
    
        <!-- A cat has to have a name, but it shouldn' be too long. -->
        <property name="Name">
          <column name="Name" length="16" not-null="true" />
        </property>
        <property name="Sex" />
        <property name="Weight" />
      </class>
    
    </hibernate-mapping>
    
    这里有一个标记挺有意思的:
    <generator class="uuid.hex" />
    他说明id字段是一个数据库标识符生成器,程序会自动产生一个32 hex character 用于标识一条数据
     
    六、使用持久化管理器(ISession) ,写入数据
    NHibernate的ISession了。它是一个 持久化管理器, 我们通过ISession来从数据库中存取Cat

    首先,我们要从ISessionFactory中获取一个ISession(NHibernate的工作单元)。

    ISessionFactory sessionFactory =
                new Configuration().Configure().BuildSessionFactory();
    ISessionFactory代表一个数据库,并且使用一个XML配置文件(Web.config或者hibernate.cfg.xml)。 NHibernate通过对Configuration().Configure()的调用来装载配置文件,并初始化成一个Configuration实例。通过Configuration实例创建一个ISessionFactory。 在创建 ISessionFactory之前(它是不可变的),你可以访问Configuration来设置其他属性(甚至修改映射的元数据)。
    ISessionFactory通常只是被初始化一次

    下面实现了一个名为NHibernateHelper的帮助类:

    using System;
    using System.Web;
    using NHibernate;
    using NHibernate.Cfg;
    
    namespace QuickStart
    {
        public sealed class NHibernateHelper
        {
            private const string CurrentSessionKey = "nhibernate.current_session";
            private static readonly ISessionFactory sessionFactory;
    
            static NHibernateHelper()
            {
                sessionFactory = new Configuration().Configure().BuildSessionFactory();
            }
    
            public static ISession GetCurrentSession()
            {
                HttpContext context = HttpContext.Current;
                ISession currentSession = context.Items[CurrentSessionKey] as ISession;
    
                if (currentSession == null)
                {
                    currentSession = sessionFactory.OpenSession();
                    context.Items[CurrentSessionKey] = currentSession;
                }
    
                return currentSession;
            }
    
            public static void CloseSession()
            {
                HttpContext context = HttpContext.Current;
                ISession currentSession = context.Items[CurrentSessionKey] as ISession;
    
                if (currentSession == null)
                {
                    // No current session
                    return;
                }
    
                currentSession.Close();
                context.Items.Remove(CurrentSessionKey);
            }
    
            public static void CloseSessionFactory()
            {
                if (sessionFactory != null)
                {
                    sessionFactory.Close();
                }
            }
        }
    }

    这个类不用考虑ISessionFactory,应为它被设置为static类型的,并且将ISessionhttp请求之中。

    ISessionFactory是安全线程,可以由很多线程并发访问并获取到ISessions。 单个ISession不是安全线程对象,它只代表与数据库之间的一次操作。 ISession通过ISessionFactory获得并在所有的工作完成后关闭。

    在程序自动添加的页面Default.aspx的CodeBehind文件Default.aspx.cs里边添加代码,操作数据库中的Cat表

            protected void Page_Load(object sender, EventArgs e)
            {
                ISession session = NHibernateHelper.GetCurrentSession();
                ITransaction tx = session.BeginTransaction();
                Cat p = new Cat();
    
                p.Name = "pp"; //不管数据库中是否允许ID为空,都不需要设置ID,设置了也没用。。。。。
                p.Sex = 'F';
                p.Weight = 102f;
    
                session.Save(p);  //将p保存到数据库里边
                //session.Load(p, "5f649160704f4688a1cdf1c1893877a9");
    
                tx.Commit();
                NHibernateHelper.CloseSession();  //关闭Session
            }

    七、读取数据:
    和写入数据很像:
    修改Default.aspx.cs里边的代码:
            protected void Page_Load(object sender, EventArgs e)
            {
                ISession session = NHibernateHelper.GetCurrentSession();
                ITransaction tx = session.BeginTransaction();
                Cat p = new Cat();
    
                p.Name = "pp";
                p.Sex = 'F';
                p.Weight = 102f;
    
                //session.Save(p);
                session.Load(p, "5f649160704f4688a1cdf1c1893877a9");  刚才写入数据时生成的ID,需要手动从数据库里边拷贝出来。。
    
                tx.Commit();
                NHibernateHelper.CloseSession();
    
                Response.Write(p.Name);
    
            }
    总结:
    至此,俺的第一个NHibernate程序在拷贝和粘贴中完成了。NHibernate是你不用再直接跟ADO.Net打交道了,不用刻意去房子SQL语句的写法什么的了.
    更多功能,有待俺继续探索
    更新数据库,或读取数据库时,NHibernate是怎样操作数据的呢?
    贴两个SqlServerProfiler监视到的Sql语句:
    插入:
    exec sp_executesql N'INSERT INTO Cat (Name, Sex, Weight, Id) VALUES 
    (@p0, @p1, @p2, @p3)',N'@p0 nvarchar(16),@p1 nchar(1),@p2 real,@p3 nvarchar(4000)',
    @p0=N'pp',@p1=N'F',@p2=102,@p3=N'9b2337d79f54403ab78ff6198ec9f68b'

    读取:
    exec sp_executesql N'SELECT cat0_.Id as Id0_0_, cat0_.Name as Name0_0_, 
    cat0_.Sex as Sex0_0_, cat0_.Weight as Weight0_0_ FROM Cat cat0_ WHERE 
    cat0_.Id=@p0',N'@p0 nvarchar(4000)',@p0=N'9b2337d79f54403ab78ff6198ec9f68b'
    更新:
    exec sp_executesql N'UPDATE Cat SET Name = @p0, Sex = @p1, Weight = @p2 
    WHERE Id = @p3',N'@p0 nvarchar(16),@p1 nchar(1),@p2 real,@p3 nvarchar(4000)',
    @p0=N'ddddddd',@p1=N'F',@p2=102,@p3=N'9b2337d79f54403ab78ff6198ec9f68b'
     
    都是些很简单的SQL语句  呵呵
    Technorati 标签: NHibernate

     
  • 相关阅读:
    4.iptables 网络防火墙
    iterator not dereferencable问题
    秒杀多线程系列中的题目
    说说僵尸和孤儿进程的那点儿事
    Linux的fork()写时复制原则(转)
    linux进程原语之fork()
    linux--多进程进行文件拷贝
    哈夫曼树与哈夫曼编码
    csp公共钥匙盒
    字典树
  • 原文地址:https://www.cnblogs.com/zyqgold/p/1810864.html
Copyright © 2020-2023  润新知