代码改变世界

使用NHibernate(8)-- 延迟加载

  FuzhePan  阅读(338)  评论(0编辑  收藏  举报

1,延迟加载。

延迟加载,即用到的时候再加载数据。这种机制是非常有情怀的,比如一篇中的用户实体有标签、问题等导航属性,如果只是用到用户名去查询整个实体,则把相关的标签和问题也都加载,性能会比较低。而有了延迟加载机制之后就可以做到查询用户实体只加载用户数据,访问到标签或问题等属性的时候再去加载这些数据。

如果使用Linq To NHibernate,则可以使用Linq提供的延迟加载机制,对于这种,是linq提供的机制,就不讨论了。

需要注意的是,如果查询出用户实体之后,关闭了Session。则延迟加载的时候会抛出异常。这是因为关闭session数据库连接被关闭,无法继续查询数据。

NHibernate默认是开启延迟加载的,也可以通过Lazy="false"属性关闭某个属性的延迟加载机制,这时会立即加载。

可以通过查看生成的sql来验证这种情况,再此就不写示例代码了。

2,延迟加载的原理。

延迟加载一般是通过代理模式来实现的,NHibernate会为我们的实体生成一个继承与该实体的代理,并重写父类的方法(这也是NHibernate要求我们的实体属性都必须是Virtual的原因)。

比如对于我们的User类,会生类似如下的代理类:

public class UserProxy:User
{

    public override List<Question> Questions

    {

        get

        {

            base.Questions = ...//加载数据

            return base.Questions;

        }

        set

        {

            base.Questions = value;

        }

    }

}

因为继承的关系,所以把代理类赋值给User类是没有问题的,同时由于多态,调用User的Question的时候实际调用的是代理类的属性。

3,方法Get和Load的区别。

Session有两个查询数据的方法,及Get和Load。Get方法会立即从数据库加载对象,而Load方法返回的是一个代理对象,当使用这个代理对象时,再去查询数据库,从而实现延迟加载。

这一点也可以通过监视生成的sql来实现。

4,Linq To NHibernate中的立即查询。

有时候,我们明确知道在某个业务逻辑中会用到当前实体的某个导航属性,希望查询的时候一次查询出来提高效率,而不是先加载实体,再加载导航属性。这时候可以用Linq To NHibernate中的立即查询来实现。

NHibernate提供了四种方法:Fetch及ThenFetch,FetchMany及ThenFetchMany。

Fetch用来加载关联关系,加载User的同时加载导航属性Question集合:

var users = session.Query<User>().Fetch(u=>u.Questions).ToList();

如果Question实体又包含Answer的导航属性,希望也一并加载出来,则可以使用ThenFetch:

var users = session.Query<User>().FetchMany(u=>u.Questions).ThenFetch(q=>q.Answers).ToList();

对于Fetch和FetchMany的区别:

针对上面的代码Fetch返回的是Question集合,不能针对返回结果继续ThenFetch。

而FetchMany返回的是Question,可以对其结果继续进行ThenFetch。

编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
点击右上角即可分享
微信分享提示