NHibernate 延迟加载与立即加载 (第七篇)

一、延迟加载

  延迟加载可以理解为:当需要用的时候才加载。

  假设我们数据库有一个Person对象,一个Country对象,其中Person属于Country,一对多关系。当我们Get()一个Person对象的时候。并不立即把Country对象也加入来,而是当我们的代码执行到要通过Person调用Country对象的时候,NHibernate才到数据库去查询对应的Country对象,这就叫延迟加载。相反,如果我们Get()一个Person对象,并且连与此Person对象相关联的Country对象也一起加载到程序中,这就叫立即加载。

  延迟加载必须在Session的周期内,如果查询了数据,但是程序中又并没有用到的时候,Session又关闭了。这时NHibernate就不能为我们实现延迟加载。

  一对多示例:

  Person - Country是一对多关系。

复制代码
        static void Main(string[] args)
        {
            ISessionFactory SessionFactory = (new Configuration()).Configure().BuildSessionFactory(); ;
            ISession session = SessionFactory.OpenSession();

            PersonModel p = session.Get<PersonModel>(1);
            Console.WriteLine(p.Name);
            Thread.Sleep(5000);
            Console.WriteLine(p.Country.CountryName);

            Console.ReadKey();
        }
复制代码

  来看以上代码执行结果:

  

  以上程序执行的过程是,当我们查询Person时,NHibernate加载出Person对象。但是与其对应的Country对象并不从数据库查出。而当我们需要用到Country对象的内容时,NHibernate此时才再次发出一条SQL语句执行,获得对应的Country对象。

  禁用延迟加载:

  假如我们在Country.hbm.xml映射文件里面设置非延迟加载呢?

  <class lazy="false" name="Model.CountryModel, Model" table="Country">

  我们在来看看执行结果:

  

  这次只需看到上面的SQL语句有个inner join就够了。当我们禁止延迟加载之后,NHibernate一次过从数据库就加载出了与Person对应的Country对象。而且,在5秒钟之后,也并没有再执行SQL语句,因为一早就已经获取到了Country对象。

  关闭Session:

  首先,记得先把lazy="false"改回true;

  Program.cs

复制代码
        static void Main(string[] args)
        {
            ISessionFactory SessionFactory = (new Configuration()).Configure().BuildSessionFactory();

            PersonModel p = new PersonModel();
            using (ISession session = SessionFactory.OpenSession())
            {
                p = session.Get<PersonModel>(1);
                Console.WriteLine(p.Name);   
            }
            Console.WriteLine(p.Country.CountryName);

            Console.ReadKey();
复制代码

  然后当执行到需要Country对象的时候,程序报错。

  

  由此,我们得到,当Session关闭之后,就没有办法再延迟加载数据了。一定要注意。

  另外,多对多关系中,有一点需要注意,就是延迟加载的时候,加载多少个才合适呢?这个NHibernate真不知道。对于这种情况,最后就是自己程序控制。

二、立即加载

  立即加载的第一种方法,通过上面的例子。设置lazy="false"就能够做到。另外,也能够通过编程的方式,强制使用立即加载。

  NHibernateUtil.Initialize

  program.cs

复制代码
        static void Main(string[] args)
        {
            ISessionFactory SessionFactory = (new Configuration()).Configure().BuildSessionFactory();

            PersonModel p = new PersonModel();
            using (ISession session = SessionFactory.OpenSession())
            {
                p = session.Get<PersonModel>(1);
                NHibernateUtil.Initialize(p.Country);
            }
            Console.WriteLine(p.Country.CountryName);

            Console.ReadKey();
        }
复制代码

  以上代码,正常输出:

  

  这里,需要ISession也关闭了,但是却能直接执行,因为Country的数据,一早已经加载到程序中,不再需要ISession。

  抓取策略

  另外,通过抓取策略,也能够强制使用立即加载机制。

  这次我们倒过来,我们从Country查Person。

  我们把Country.hbm.xml修改为如下:

    <!-- 一个Country里面有多个Person -->
    <set name="ListPerson" table="Person" generic="true" inverse="true" fetch="join">
      <key column="CountryId" foreign-key="FK_Person_Country"/>
      <one-to-many class="Model.PersonModel,Model"/>
    </set>

  Program.cs

复制代码
        static void Main(string[] args)
        {
            ISessionFactory SessionFactory = (new Configuration()).Configure().BuildSessionFactory();

            CountryModel c = new CountryModel();
            using (ISession session = SessionFactory.OpenSession())
            {
                c = session.Get<CountryModel>(1);
            }
            foreach (PersonModel p in c.ListPerson)
            {
                Console.WriteLine(p.Name);
            }

            Console.ReadKey();
        }
复制代码

  以上代码,在关闭ISession之后,再查找Country下的Person输出结果如下:

  

  如果去掉fetch="join",一样报ISession已关闭错误。

  关于延迟加载与立即加载,就了解这么多。以后如果还有用到更深入的再补充。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值