• NH菜鸟笔记Ⅰ


    NH菜鸟笔记

      

    本文是看了"京哥"NH系列后写的随笔,感谢京哥感谢博客园,感谢WZMC的实验室给我这次写笔记的机会。

     

    从一个简单的NH控制台程序出发

     

    1. NHibernate的环境

    我使用的开发环境:Microsoft Visual Studio 2008 SP1+SQL Server 2005 Express+NHibernate-3.0.0.Alpha2

     

    本图来自京哥博客,http://www.cnblogs.com/lyj/archive/2008/10/30/1323099.html

     

    下载NHibernate最新版本(包括源码、发布版本、参考文档、API文档,可选择下载)http://sourceforge.net/projects/nhibernate/

     

    2. 建立数据库表

    打开SQL 2005,新建一个新的数据库NHibernateSample,创建四个表:分别为客户表Customer、订单表Order、订单产品表OrderProduct、产品表Product。

     

    3. 创建C#类库项目

    使用VS2008创建C#类库的项目,命名为NHibernateSample。打开项目文件夹,在其项目文件目录上新建SharedLibs文件夹,把下载NHibernate相关程序集文件拷贝到SharedLibs文件夹下。如下图,这里我选择Castle框架动态代理:

     

    创建项目,结构如下

     

     Domain(领域模型):用于持久化类和O/R Mapping操作

     Data(Data Access Layer数据访问层):定义对象的CRUD操作

     Data.Test(数据访问层测试):对数据访问层的测试,这里我使用Nunit单元测试框架

     项目引用

     Domain:引用Iesi.Collections.dll程序集(Set集合在这个程序集中)、Castle动态代理NHibernate

     Data:引用NHibernate.dllIesi.Collections.dllNHibernate.ByteCode.Castle程序集和动态代理相关程序集(Castle.DynamicProxy2Domain引用

     Data.Test:引用NHibernate.dll、Iesi.Collections.dll、NHibernate.ByteCode.Castle程序集和DomainData引用

     

    4.设计Domain

    4-1.编写持久化类

    现在为Customer编写持久化类来映射成为数据库表。新建一个Customer.cs类文件:

    namespace NHibernateSample.Domain
    {
        public class Customer
        {
            /// <summary>
            /// NHibernate默认使用代理功能,要求持久化类不是sealed的,
            /// 而且其公共方法、属性和事件声明为virtual。
            /// 在这里,类中的字段要设置为virtual
            /// </summary>
            public virtual int Id { get; set; }
            public virtual string FirstName { get; set; }
            public virtual string LastName { get; set; }
        }
    }
    

    4-2.编写映射文件

    我们要为Microsoft Visual Studio 2008添加编写NHibernate配置文件智能提示的功能。只要在下载的NHibernate里找到configuration.xsdnhibernate-mapping.xsd两个文件并复制到X:\Program Files\Microsoft Visual Studio 9.0\Xml\Schemas目录即可。

    NHibernate要知道怎样去加载和存储持久化类的对象。这正是NHibernate映射文件发挥作用的地方。映射文件包含了对象/关系映射所需的元数据。元数据包含持久化类的声明和属性到数据库的映射。映射文件告诉NHibernate它应该访问数据库里面的哪个表及使用表里面的哪些字段。

    这里,我为Customer.cs类编写映射文件。新建一XML文件,命名为Customer.hbm.xml

    XML文件的默认生成操作为内容,这里需要修改为嵌入的资源生成

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
       assembly="NHibernateSample.Domain"
       namespace="NHibernateSample.Domain">
    
      <class name ="Customer">
        <id name="Id" column ="CustomerId">
          <generator class ="assigned"/>
        </id>
        <property name ="FirstName"/>
        <property name ="LastName"/>
      </class>
    </hibernate-mapping>
    

     以上的两个文件关系密切,xml中的propertycustomer.cs中的成员是对应的。否则无法编译成功。因为我们在映射文件中把原来的CustomerId改成Id,因此在接下来的query语句中,我们应该使用Id而不是CustomerId,如Session.CreateQuery("select Id from Customer ").List<int>();

     

    5. 编写数据访问层 

    5-1.辅助类

    我们要从ISessionFactory中获取一个ISession(NHibernate的工作单元)。ISessionFactory可以创建并打开新的Session。一个Session代表一个单线程的单元操作。 ISessionFactory是线程安全的,很多线程可以同时访问它。ISession不是线程安全的,它代表与数据库之间的一次操作。ISession通过ISessionFactory打开,在所有的工作完成后,需要关闭。 ISessionFactory通常是个线程安全的全局对象,只需要被实例化一次。我们可以使用GoF23中的单例(Singleton)模式在程序中创建ISessionFactory。这个实例我编写了一个辅助类NHibernateHelper 用于创建ISessionFactory并配置ISessionFactory和打开一个新的Session单线程的方法,之后在每个数据操作类可以使用这个辅助类创建ISession 

    namespace NHibernateSample.Domain
    {
        public  class NHibernateHelper
        {
            private  ISessionFactory _sessionFactory;
            public NHibernateHelper()
            {
                _sessionFactory = GetSessionFactory();
            }
            private  ISessionFactory GetSessionFactory()
            {
                return (new Configuration()).Configure().BuildSessionFactory();
            }
            public  ISession GetSession()
            {
                return _sessionFactory.OpenSession();
            }
        }
    }
    

     

    5-2.编写操作

    Data中新建一类NHibernateSample.cs,编写一方法GetCustomerId用于读取客户信息。在编写方法之前,我们需要初始化Session

    namespace NHibernateSample
    {
        public class NHibernateSample
        {
            protected ISession Session { get; set; }
            public NHibernateSample(ISession session)
            {
                Session = session;
            }
            public void CreateCustomer(Customer customer)
            {
                Session.Save(customer);
                Session.Flush();
            }
            public Customer GetCustomerById(int customerId)
            {
                return Session.Get<Customer>(customerId);
            }   
        }
    }
    

    6.编写数据访问层的测试

    6-1.配置NHibernate

    我们可以几种方法来保存NHibernate的配置,具体以后来介绍,这里我们使用hibernate.cfg.xml文件来配置,不过不必担心,这个文件我们可以在NHibernate-3.0.0.Alpha2-bin\Configuration_Templates文件夹下找到,直接复制到Data.Test中修改一下配置信息和文件输出属性就可以了。

    <?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">
          Data Source=.\SQL2005;Initial Catalog=NHibernateSample;
          Integrated Security=True;Pooling=False
        </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>
        <property name="proxyfactory.factory_class">
          NHibernate.ByteCode.Castle.ProxyFactoryFactory,
          NHibernate.ByteCode.Castle
        </property>
        <mapping assembly="NHibernateSample.Domain"/>
      </session-factory>
    </hibernate-configuration>
    

    XML文件的默认复制到输出目录不复制,这里需要修改为始终复制

    6-2.测试

    好了,终于可以使用我们的方法了,这里新建一个测试类NHibernateSampleFixture.cs 调用NHibernateSample类中GetCustomerId方法查询数据库中CustomerId1的客户,判断返回客户的Id是否为1

    namespace NHibernateSample.Data.Test
    {
        public class NHibernateSampleFixture
        {
            private NHibernateSample _sample;
            NHibernateHelper nhh = new NHibernateHelper();
            public void TestFixtureSetup()
            {
                _sample = new NHibernateSample(nhh.GetSession());
            }
    	public void CreateCustomer()
            {
                var tempCutomer = new Customer {Id="0", FirstName = "Akon", LastName = ".S" };
                _sample.CreateCustomer(tempCutomer);
            }
            public void GetCustomerByIdTest()
            {
                Customer customer = _sample.GetCustomerById(0);
                Console.WriteLine("------------------------------------------");
                Console.WriteLine("CustomerId:" + customer.Id);
                Console.WriteLine("FirstName:" + customer.FirstName);
                Console.WriteLine("LastName:" + customer.LastName);
                Console.WriteLine("------------------------------------------");
            }    }
    }
    
    namespace NHibernateSample.Data.Test
    {
        class Program
        {
            public static void Main()
            {
                NHibernateSampleFixture nhsf = new NHibernateSampleFixture();
                nhsf.TestFixtureSetup();
                nhsf.GetCustomerByIdTest();
                Console.ReadLine();
            }
        }
    }
    

     

    7.巧用组件

    使用组件(component)NHibernate中,提供了组件(Component)和动态组件来帮助我们完成这件事情。其实组件(component)在NHibernate中为了不同目的被重复使用。这里我们使用它来依赖对象。

    我们来用FullName来表示FirstNameLastName的相加。先添加一个Name的类

    namespace NHibernateSample.Domain
    {
        public class Name
        {
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public string FullName
            {
                get
                {
                    return FirstName + LastName;
                }
            }
        }
    }
    

    然后相应的修改Customer的持久化类和映射文件.

    namespace NHibernateSample.Domain
    {
        public class Customer
        {
            /// <summary>
            /// NHibernate默认使用代理功能,要求持久化类不是sealed的,
            /// 而且其公共方法、属性和事件声明为virtual。
            /// 在这里,类中的字段要设置为virtual
            /// </summary>
            public virtual int Id { get; set; }
            public virtual Name FName { get; set; }
        }
    }
      <class name ="Customer">
        <id name="Id" column ="CustomerId">
          <generator class ="assigned"/>
        </id>
        <!--<property name ="FirstName"/>
        <property name ="LastName"/>-->
        <component name="FName" >
          <property name="FirstName" column="FirstName"/>
          <property name="LastName" column="LastName"/>
        </component>
      </class>
    

    这样就能获取到需要的信息。

  • 相关阅读:
    vue路由懒加载
    Git文档
    Redis启动多个实例,并以windows服务方式运行
    windwos service安装命令
    sqlserver随机查询
    Redis 主从配置
    Unity3D 学习资料
    MAC常用终端命令
    服务器证书安装配置指南(IIS7)
    sql Exists与in 的区别
  • 原文地址:https://www.cnblogs.com/TivonStone/p/1826239.html
Copyright © 2020-2023  润新知