• NHibernate延迟加载


    代码
    1)测试数据库与测试数据
    Database目录下面是测试用的数据库文件NHibernatePractice2.mdf,包含有两张数据表Department与Employee,其中Employee表的DepartmentId是外键,引用Department的主键。表中测试数据如下:

    为了测试方便,你可以直接附加数据库文件NHibernatePractice2.mdf到SQL Server2005,否则也可以自己创建数据库,然后手工(或使用NHibernate的SchemaExport)创建数据表、插入测试数据。
    2) 引用的类库Lib
    Lib目录下面是引用的dll,包括:NHibernate.dll、nunit.framework.dll、Castle.DynamicProxy2.dll、Iesi.Collections.dll、log4net.dll。为项目添加这些引用。
    3)hibernate.cfg.xml
    创建NHibernate配置文件,注意该文件属性设置为“Copy always”:配置如下:

    Code
    <?xml version="1.0" encoding="utf-8" ?>
    <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=NHibernatePractice2;Integrated Security=SSPI</property>
        
    <property name="show_sql">true</property>
        
    <mapping assembly="NHibernatePractice2"/>
        
      
    </session-factory>
    </hibernate-configuration>
    4)NHibernateHelper.cs
    接下来创建NHibernate辅助类,用于获取NHibernate的session,其中应用了Singleton模式:

    Code
    namespace NHibernatePractice2
    {
        
    //辅助类,用于获取Session
        
    //应用了Singleton设计模式
        public class NHibernateHelper
        {
            
    //Eagerly Initialize,确保线程同步
            private static ISessionFactory _sessionFactory = 
                
    new Configuration().Configure().BuildSessionFactory();

            
    private NHibernateHelper()
            {
            }

            
    public static ISession OpenSession()
            {
                
    return _sessionFactory.OpenSession();
            }
        }
    }
    5)Domain Class
    在Domain目录下面创建两个实体类,代码非常简单,分别如下:
    Department.cs:

    Code
    namespace NHibernatePractice2.Domain
    {
        
    public class Department
        {
            
    public virtual int Id { getset; }
            
    public virtual String Name { getset; }

            
    //关联集合
            public virtual IList<Employee> Employees { getset; }

        }
    }
    Employee.cs:

    Code
    namespace NHibernatePractice2.Domain
    {
        
    public class Employee
        {
            
    public virtual int Id { getset; }
            
    public virtual String Name { getset; }

            
    public virtual Department Department { getset; }
        }
    }
    6)Mapping文件
    在Mappings目录下为Department与Employee分别创建映射文件(注意文件属性设置为“Embedded Resource”):
    Department.hbm.xml:

    Code
    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                assembly
    ="NHibernatePractice2"
                
    namespace="NHibernatePractice2.Domain">
      
    <class name="Department">
        
    <id name="Id" >
          
    <generator class="native" />
        
    </id>
        
    <property name="Name"/>
        
        
    <!-- 设置fetch="join"抓取策略(global fetching strategy)-->
        
    <!--该策略会被HQL忽略,但是不会被Get、Criteria忽略-->
        
    <bag name="Employees" inverse="true" fetch="join">
          
    <key column="DepartmentId" />
          
    <one-to-many class="Employee"/>
        
    </bag>

        
    <!--若设置成lazy="false"(global fetch plan)-->
        
    <!--则都不会被HQL、Get、Criteria忽略-->
        
    <!--<bag name="Employees" inverse="true" lazy="false">
          
    <key column="DepartmentId" />
          
    <one-to-many class="Employee"/>
        
    </bag>-->

      
    </class>
    </hibernate-mapping>
    Employee.hbm.xml:

    Code
    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                assembly
    ="NHibernatePractice2"
                
    namespace="NHibernatePractice2.Domain">
      
    <class name="Employee">
        
    <id name="Id" >
          
    <generator class="native" />
        
    </id>
        
    <property name="Name"/>
        
        
    <many-to-one name="Department" class ="Department" column="DepartmentId" foreign-key="FK_Employee_Department" not-null="true"/>
      
      
    </class>
    </hibernate-mapping>

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                assembly
    ="NHibernatePractice2"
                
    namespace="NHibernatePractice2.Domain">
      
    <class name="Employee">
        
    <id name="Id" >
          
    <generator class="native" />
        
    </id>
        
    <property name="Name"/>
        
        
    <many-to-one name="Department" class ="Department" column="DepartmentId" foreign-key="FK_Employee_Department" not-null="true"/>
      
      
    </class>
    </hibernate-mapping>  大家注意到,我在Department.hbm.xml文件中将关联集合已经设置为fetch="join"
    7)测试类NHibernatePractice2Test.cs
    在Test目录下创建测试类NHibernatePractice2Test.cs,代码如下:

    Code
    namespace NHibernatePractice2.Test
    {
        [TestFixture]
        
    public class NHibernatePractice2Test
        {
            
    //要查找的Department数据的Id=1
            int departmentId = 1;
            
            [Test]
            
    //测试Get方法获取数据
            public void TestGet()
            {
                Department fromDb 
    = null;

                
    //如果mapping文件中设置了fetch="join",
                
    //Get查询会在一条sql中同时获取Department以及所属的Employee
                using (ISession session = NHibernateHelper.OpenSession())
                
    using (ITransaction transaction = session.BeginTransaction())
                {
                    
    //调用Get方法
                    fromDb = session.Get<Department>(departmentId);
                    
                    transaction.Commit();
                }

                Assert.IsNotNull(fromDb);
                
    //由于上面的Get查询同时获取了Department以及所属的Employee,测试成功
                Assert.AreEqual(2, fromDb.Employees.Count);
            }

            [Test]
            
    //测试Criteria获取数据
            public void TestGetByCriteria()
            {
                Department fromDb 
    = null;

                
    //如果mapping文件中设置了fetch="join",
                
    //Criteria查询会在一条sql中同时获取Department以及所属的Employee
                using (ISession session = NHibernateHelper.OpenSession())
                
    using (ITransaction transaction = session.BeginTransaction())
                {
                    fromDb 
    = session.CreateCriteria(typeof(Department))
                        .Add(Restrictions.Eq(
    "Id", departmentId))
                        .UniqueResult
    <Department>();

                    transaction.Commit();
                }

                Assert.IsNotNull(fromDb);
                
    //由于上面的Criteria查询同时获取了Department以及所属的Employee,测试成功
                Assert.AreEqual(2, fromDb.Employees.Count);
            }

            [Test]
            
    //测试HQL获取数据
            public void TestGetByHQL()
            {
                Department fromDb 
    = null;

                
    //如果mapping文件中设置了fetch="join",
                
    //HQL查询会忽略fetch="join",因此只获取Department,不会获取Employee
                using (ISession session = NHibernateHelper.OpenSession())
                
    using (ITransaction transaction = session.BeginTransaction())
                {
                    fromDb 
    = session.CreateQuery("from Department d where Id=:id")
                        .SetInt32(
    "id", departmentId)
                        .UniqueResult
    <Department>();

                    transaction.Commit();
                }

                Assert.IsNotNull(fromDb);
                
    //由于上面HQL查询只获取Department,没有获取Employee(也就是关联集合Employees未被初始化),
                
    //同时session已经关闭(transaction.Commit),所以访问关联集合fromDb.Employees将抛出异常NHibernate.LazyInitializationException
                Assert.AreEqual(2, fromDb.Employees.Count);
            }
        }
    }
      由于例子本身就非常简单,再加上已对代码进行了详细的注释,所以我这里只做个简单的介绍。3个测试方法TestGet()、TestGetByCriteria()、TestGetByHQL(),分别测试NHibernate的Get、Criteria和HQL获取数据。这里要注意的是,每个测试方法在验证前都进行了transaction.Commit();,效果就是关闭当前session,使查询得到的实体数据处于detached状态。如果在获取Department数据时没有加载Employees集合数据,这样当验证Assert.AreEqual(
    2, fromDb.Employees.Count);时会抛出NHibernate.LazyInitializationException异常。
  • 相关阅读:
    SQL舊面版與標准版不能互導數據
    今天總算可以繼續寫日記了
    MDAC2.7没有安装,控件不能运行
    希望5月份网络能开通
    SQLITE入门逐步讲解SQLITE命令行(一)
    C#使用SQLite数据库的代码示例
    红外遥控 Arduino 实例
    SQLite数据库是中小站点CMS的最佳选择
    防止 SQLite 数据库被下载的方法
    关于Linux下的Grep命令简介
  • 原文地址:https://www.cnblogs.com/hubcarl/p/1680563.html
Copyright © 2020-2023  润新知