NHibernate iStatelessSession 在预先获取时返回重复的父实例



我正在尝试获取一个根实体并急于获取它的子实体。但是因为我使用的是 NHibernate 的IStatelessSession,所以它为每个孩子返回根实体的副本。使用ISession,它将通过以下方式解决

.TransformUsing(new DistinctRootEntityResultTransformer()) 

但对于IStatelessSession来说,事实并非如此。

基本上是关于下面的代码,其中只有一个 Parent 实例,包含 3 个孩子。

var result = session.QueryOver<Parent>()
.Fetch(i => i.Childs).Eager();

这将返回 3 个重复的 Parent 实例,而不仅仅是一个。有人对此有解决方案吗?

我会

说:不要使用StatelessSession。它不适合此用例。

13.2. 无状态会话接口

或者,NHibernate提供了一个面向命令的API,可用于以分离对象的形式将数据流式传输到数据库和从数据库流式传输数据。IStatelessSession 没有与之关联的持久性上下文,并且不提供许多更高级别的生命周期语义。特别是,无状态会话不实现第一级缓存,也不与任何二级或查询缓存交互。它不实现事务性后写或自动脏检查。使用无状态会话执行的操作永远不会级联到关联的实例。集合被无状态会话忽略。通过无状态会话执行的操作绕过 NHibernate 的事件模型和拦截器...

我只是尝试在这里解释一下:NHibernate:选择一到多左联接 - 从父级获取 X 个最新,这里的问题是,您的 JOIN 导致此 SQL 结果,该结果不适合分页(您迟早需要)

PARENT1 CHILD1
PARENT1 CHILD2
PARENT1 CHILD3
PARENT2 CHILD4
PARENT2 CHILD5 // if we would take 5 records, the parent2 won't get child6
PARENT2 CHILD6

所以这个结果集不是要走的路。我强烈建议:使用

  • 标准会话,是使用(让它立即处置)
  • 加载根实体列表(父实体)和
  • 让 NHibernate 延迟加载他们的子级 - 在单独的 SQL 查询中。

查询可以/应该如下所示:

ISessionFactory factory = ...;
using (var session = factory.OpenSession())
{
    var list = session.QueryOver<Parent>()
    .Skip(100)
    .Take(25)
    .List<Parent>();
    list.Last() // this will load all occupations at once
        .Childs // if batch-size is higher than page size
        .Any(); // otherwise touch more items
} // session is closed and disposed

如上面的代码片段所示,为了避免 1 + N 问题,我们必须使用智能制图功能之一:

19.1.5. 使用批量获取

NHibernate可以有效地利用批量获取,也就是说,如果访问一个代理(或集合),NHibernate可以加载多个未初始化的代理。批量提取是对惰性选择提取策略的优化。有两种方法可以调整批量提取:在类和集合级别。

类/实体的批量提取更容易理解。假设您在运行时遇到以下情况:您在 ISession 中加载了 25 个 Cat 实例,每个 Cat 都有一个对其所有者的引用,即一个人。Person 类使用代理 lazy="true" 进行映射。如果你现在遍历所有猫并调用猫。每个所有者,NHibernate将默认执行25个SELECT语句,以检索代理所有者...

父映射应该是这样的:

HasMany(x => x.Childs)
    ...
    .BatchSize(100) // should be at least 25

请同时检查这些:

  • 如何在 NHibernate 中不重复地预先加载关联?
  • NHibernate QueryOver与Fetch导致多个sql查询和数据库命中
  • 这是在 NHibernate 中预先加载子集合的正确方法吗

注意:有些人可能会建议您使用结果透氧体,就像您尝试过的那样。此解决方案可能有效,但在 C# 中在内存中完成,因此加载所有数据(多行)然后缩小。我永远不会使用它。检查:Criteria.DISTINCT_ROOT_ENTITY与投影。

最新更新