zoukankan      html  css  js  c++  java
  • NHibernate初学体验记

          NHibernate 是一个基于.Net 的针对关系型数据库的对象持久化类库。NHibernate 来源于优秀的基于Java的关系型持久化工具Hibernate。NHibernate持久化你的.Net 对象到关系型数据库,远胜于写SQL去从数据库存取对象。你的代码仅仅和对象关联,NHibernat 自动产生SQL语句,并确保对象提交到正确的表和字段中去。NHibernate极大地减少了数据层代码的编写,当然提高了开发的效率和质量。体验一下吧。(有关Hibernate的资料请参考文末)

    测试环境:单机安装Win2003SP2 + SQL2000 + .NET2.0 + VS2005

    一、下载安装NHibernate

    下载地址:http://sourceforge.net/project/showfiles.php?group_id=73818

    运行安装程序NHibernate-1.2.1.GA.msi,默认情况下“C:"Program Files"NHibernate”目录下。

    二、准备数据库

    1.在SQL Server2000下创建NHibernate数据库;

    2.执行如下SQL语句创建数据表users:

    use NHibernate

    go

    CREATE TABLE users (

     LogonID nvarchar(20) NOT NULL default '0',

     Name nvarchar(40) default NULL,

     Password nvarchar(20) default NULL,

     EmailAddress nvarchar(40) default NULL,

     LastLogon datetime default NULL,

     PRIMARY KEY (LogonID)

    )

    go

    三、开发程序
    1.在VS2005中新建类库项目NHibernate.Examples,同时选中“创建解决方案目录”复选框。
       
        
    2.在NHibernate.Examples类库项目创建类文件User.cs,内容如下。(注:一个User对象对应数据表users中的一条记录。)

    using System;

    namespace NHibernate.Examples.QuickStart

    {

        public class User

        {

            private string id;

            private string userName;

            private string password;

            private string emailAddress;

            private DateTime lastLogon;

            public User()

            {

            }

            public string Id

            {

                get { return id; }

                set { id = value; }

            }

            public string UserName

            {

                get { return userName; }

                set { userName = value; }

            }

            public string Password

            {

                get { return password; }

                set { password = value; }

            }

            public string EmailAddress

            {

                get { return emailAddress; }

                set { emailAddress = value; }

            }

            public DateTime LastLogon

            {

                get { return lastLogon; }

                set { lastLogon = value; }

            }

        }

    }

    3.在NHibernate.Examples类库项目创建映射文件User.hbm.xml,并将文件的“生成操作”属性设置为“嵌入的资源”(如图),映射文件将成为装配件的一部分。
                

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-
    2.2">
        <class name="NHibernate.Examples.QuickStart.User, NHibernate.Examples" table="users"
    lazy="false">
              <id name="Id" column="LogonId" type="String" length="20">
                  <generator class="assigned" />
              </id>
              <property name="UserName" column= "Name" type="String" length="40"/>
              <property name="Password" type="String" length="20"/>
              <property name="EmailAddress" type="String" length="40"/>
              <property name="LastLogon" type="DateTime"/>
        </class>

    </hibernate-mapping>

    让我们来看看User.hbm.xml文件中让我们感兴趣的某些行。第一个有趣的标签是class。这里我们将映射类型名称(类名和装配件)到我们数据库中的User表,这里和Hibernate有一点点的不同。你将不得不告诉NHibernate从何处提取对象。在这个例子里我们从装配件NHibernate.Examples装载类NHibernate.Examples.QuickStart.User 。NHibernate 遵循和.Net Framework同样的规则来加载类型。因此如果你在如何指定类型的方面有些混淆,请参看.Net Framework SDK。

    让我们先跳过id标签,来讨论property标签。简要看一下,你将发现NHibernate所要做的工作。name属性的值正是我们.Net 类的属性,column属性值将是我们数据库里的字段。type属性是可选的(如果你不标明,NHibernate将利用反射进行最佳的推测)。

    好了,让我们回到标签id, 你可以猜测到这个标签将是映射数据库表的主键,的确如此,id标签的组成和我们刚才看的property标签是相似的。我们映射属性到目标数据库的字段。

    内嵌的generator 标签告诉NHibernate 如何生成主键(它将恰当的为你生成主键,不管你指定何种类型,但你必须告诉它)。在我们的例子里,我们设定为assigned,意味着我们对象将自己生成主键(毕竟User对象常常需要一个UserID)。如果你执意要NHiberante为你生成主键,你感兴趣于设定uuid.hex和uuid.string(从文档中获取更多信息)

    提示:如果你仅仅是改变映射文件,你不能使用build 而应该Rebuild项目。Visual Studio.Net 不会重新编译有改变的映射文件。

    4.新建一个Windows应用程序项目NHibernateQuickStart,并添入已有的解决方案。
       

    5.在项目NHibernateQuickStart中添加对NHibernate.dll的引用(默认安装情况下在“C:"Program Files"NHibernate"bin"net-2.0"NHibernate.dll”)。
       

    6.在项目NHibernateQuickStart中添加对NHibernate.Examples类库项目的引用:
       

    7. 在项目NHibernateQuickStart中添加应用程序配置文件App.config,内容如下:(告诉NHibernate 去哪里连接数据库以及数据库的相关配置)

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

    <configuration>

     <configSections>

        <section

          name="nhibernate"

          type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

        />

     </configSections>

     <nhibernate>

        <add key="hibernate.connection.provider"

          value="NHibernate.Connection.DriverConnectionProvider"

        />

        <add key="hibernate.dialect"

          value="NHibernate.Dialect.MsSql2000Dialect"

        />

        <add key="hibernate.connection.driver_class"

          value="NHibernate.Driver.SqlClientDriver"

        />

        <add key="hibernate.connection.connection_string"

          value="Server=localhost;initial catalog=nhibernate;Integrated Security=SSPI"

        />

     </nhibernate>

    </configuration>

    8.开始编写写入数据的代码。

    (1)在项目NHibernateQuickStart中Form1窗体上添一个按钮button1,双击button1进入代码编辑界面,我们将在button1_Click事件中编写代码。

    (2)在代码中添加using声明:

    using NHibernate;

    using NHibernate.Cfg;

    using NHibernate.Examples.QuickStart;

    (3)button1_Click事件代码如下:

    private void button1_Click(object sender, EventArgs e)

            {

                Configuration cfg = new Configuration();

                cfg.AddAssembly("NHibernate.Examples");

                ISessionFactory factory = cfg.BuildSessionFactory();

                ISession session = factory.OpenSession();

                ITransaction transaction = session.BeginTransaction();

                User newUser = new User();

                newUser.Id = "joe_cool_test";

                newUser.UserName = "Joseph Cool";

                newUser.Password = "abc123";

                newUser.EmailAddress = "joe@cool.com";

                newUser.LastLogon = DateTime.Now;

                // Tell NHibernate that this object should be saved

                session.Save(newUser);

                // commit all of the changes to the DB and close the ISession

                transaction.Commit();

                session.Close();

            }

    (4)编译整个解决方案。执行生成的EXE文件NHibernateQuickStart.exe,点击button1。之后,打开数据库users表,如果产生了一条记录,则成功!

    本项目源码下载:NHibernateQuickStart1.rar

        ===================================================================================

    另外,本人还写了一个复杂点的示例,包含了增加、修改、删除、显示记录的操作:
        源码下载:NHibernateQuickStart2.rar。看了这个代码你会发现项目中充斥了如下类似的代码:

                Configuration cfg = new Configuration();

                cfg.AddAssembly("NHibernate.Examples");

                ISessionFactory factory = cfg.BuildSessionFactory();

                ISession session = factory.OpenSession();

                ITransaction transaction = session.BeginTransaction();

    如何解决这个问题呢?以后再探讨吧J

    ===================================================================================

    推荐阅读《Hibernate Quickly中文版》一书,虽然是针对Java的,但是思想是相通的,NHibernate本源于Hibernate,看了之后会Hibernate有全面深入的认识。

    其它资料:

    Hibernate官方网站:http://www.hibernate.org

    NHibernate论坛:http://www.okec.cn

    renrenqq的blog(有丰富的ORM资料):http://www.cnblogs.com/renrenqq

        (注:本人参考NHibernate官方快速指南未能测试成功,后整理本篇文档,参考了译文:http://www.okec.cn/htm_data/7/0709/194.html

    =====================================================================================================
    参考NHibernate官方快速指南编写代码遇到的问题:
    From:http://hi.baidu.com/zsea/blog/item/7d999e3d8a54c203baa1678d.html

    一、Test.Model.Person.hbm.xml(2,2): XML validation error: 未能找到元素“urn:nhibernate-mapping-2.0:hibernate-mapping”的架构信息。

           将2.0改为2.2

    二、 The following types may not be used as proxies:
             Test.Model.Person: method set_Id should be virtual
             Test.Model.Person: method get_Name should be virtual
             Test.Model.Person: method set_Name should be virtual
             Test.Model.Person: method get_Id should be virtual

             类配置文件中Class的Lazy改为false
             网上搜到的三种解决方案:
            1.   You can follow the advice of the exception and add "virtual" to all of your properties, and make sure your class is non-sealed. Obviously you'll want to do this if you think you might want to take advantage of the lazy-initializing proxy feature.   However, changing your classes may not be practical or advisable if you have a legacy codebase, or it may just bother you that a "transparent" persistence framework is dictating how you design certain aspects of your value classes.   That's where Options 2 and 3 come in.   Both of those involve changing back to the old behavior.

              2.  To change the lazy-initialization proxy setting for a specific class, you can add a "lazy='false'" attribute to the <class> mapping element.   This might look something like:
    <class
         name="NorthwindClasses.Category, NorthwindClasses"
         table="Categories"
         lazy="false"
    >
            3.  To change the lazy-initialization proxy setting for all classes in a given mapping file, you can add a "default-lazy='false'" attribute to the <hibernate-mapping> element, as follows:
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.0" default-lazy="false">
    Unfortunately, Option 3 doesn't really help you much if you do one <class> mapping per <hibernate-mapping> file, a practice which I personally follow and recommend.   It's too bad, but there doesn't seem to be any way to set this default in the <nhibernate> global configuration.   But if you do happen to have all of your <class>'s in one .hbm.xml file, "default-lazy" can help you out.


  • 相关阅读:
    《杀死比尔 卷1》(Kill Bill: Volume 1)思路.未剪切全彩版.720re.DTS[HDTVRE]
    IronPython 1.0 Release Candidate 2
    Microsoft® Visual Studio® .NET™ 2003 Service Pack 1
    Vista Transformation Pack 5.0 发布
    捡到一小猫
    《魔比斯环》(Thru The Moebius Strip)[DVDScr]
    用户控件 分类列表导航栏
    MsChart<5> 累计柱状图 分类统计
    二进制流上传图片,预览,读取显示
    Ajax无刷新数据绑定
  • 原文地址:https://www.cnblogs.com/SummerRain/p/1108627.html
Copyright © 2011-2022 走看看