这是在NHibernate中急切加载子集合的正确方法

时间:2013-11-25 17:17:00

标签: nhibernate queryover

我花了太多时间找到一个很好的方式来加载子集合。到目前为止,这就是我得到的。它有效,但我发现很难相信这是编写此查询的最佳方式

 [Fact]
    public void EagerLoadQueryOverWithFutureTest()
    {
        const long journalNr = 1470;

        var query = _repo.QueryOver().Where(s => s.JournalNr == journalNr).Future<Sag>();
        var sagsansoegning = _repo.QueryOver().Where(an => an.JournalNr == journalNr).Fetch(x => x.Sagsansoegning).Eager.Future<Sag>();
        var noter = _repo.QueryOver().Where(n => n.JournalNr == journalNr).Fetch(x => x.Noter).Eager.Future<Sag>();
        var filer = _repo.QueryOver().Where(f => f.JournalNr == journalNr).Fetch(x => x.Filer).Eager.Future<Sag>();
        var emails = _repo.QueryOver().Where(e => e.JournalNr == journalNr).Fetch(x => x.Emails).Eager.Future<Sag>();
        var journal = _repo.QueryOver().Where(j => j.JournalNr == journalNr).Fetch(x => x.Journal).Eager.Future<Sag>();
        var sagsTilstand = _repo.QueryOver().Where(t => t.JournalNr == journalNr).Fetch(x => x.Tilstand).Eager.Future<Sag>();
        var boligsocialEvalueringer = _repo.QueryOver().Where(b => b.JournalNr == journalNr).Fetch(x => x.BoligsocialEvaluering).Eager.Future<Sag>();
        var result = query.SingleOrDefault();
        result.JournalNr.Should().Be(journalNr);
        result.Emails.Should().HaveCount(c => c > 20);
        result.Filer.Should().HaveCount(c => c > 20);
    }

1 个答案:

答案 0 :(得分:1)

我想追加不同的观点,而不是如何使用“未来”只进行一次往返DB的回答。

不确定为什么需要获取所有属性。我猜你的代码可能会使用1),例如将UI或2)渲染为API,以某种方式将其序列化并将其传递给客户端。

在第一个场景中,我建议每个请求使用会话并使用延迟加载。在第二步中,我建议引入一个步骤:在将DTO传递给客户端之前构建它。这可以在会话仍然打开时完成,因此使用延迟加载。

两种情况下的延迟加载。因此,在这两种情况下,我建议使用不同的方法然后显式提取。它将使用或多或少相同数量的选择和往返DB。但最终它可能会更有效。因为所有这些工作都将留在NHibernate上

事情是用批量大小(本机)加载来改变eager-fetch(手动)加载。点击此处查看19.1.5. Using batch fetching。在这种情况下,NHibernate将处理您的查询,然后将再次使用更多查询来加载剩余数据。但只有在真的需要时

优点是,您不是您的疑问的囚徒。您可以使用实体上可以/应该可用的任何属性,直到会话打开(即,在视图呈现或序列化期间)。您不必在连接上附加另一个显式查询以获取急切数据。

所以,虽然Future可能是世界的解决方案,但是你从APP连接数据库的速度非常慢......世界上并没有使用NHibernate(ORM)。惰性映射和临时加载(具有批处理功能)的优点是从维护角度来看正确...我会说