3

我正在尝试获取一个根实体并渴望获取它的子实体。但是因为我使用的IStatelessSession是 NHibernate,所以它会为每个孩子返回根实体的副本。使用 ISession 可以解决

.TransformUsing(new DistinctRootEntityResultTransformer()) 

但对于一个IStatelessSession它不是。

基本上是关于下面的代码,其中只有一个 Parent 实例,拥有 3 个 Childs。

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

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

4

1 回答 1

2

我会说:不要使用StatelessSession。它不适合这个用例。

13.2. StatelessSession 接口

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

我只是试着在这里解释一下:NHibernate: Select one to Many Left Join - Take X latest from Parent,这里的问题是,你的 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。Person 类使用代理lazy="true" 进行映射。如果您现在遍历所有猫并在每个猫上调用 cat.Owner,NHibernate 将默认执行 25 条 SELECT 语句,以检索代理所有者...

父映射应该是这样的:

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

请检查这些:

注意:有些人可能会建议您使用 Result Transformer,就像您尝试过的那样。这个解决方案可以工作,但在 C# 中完成,在内存中,所以所有数据都被加载(多行)然后缩小。我永远不会使用那个。检查:Criteria.DISTINCT_ROOT_ENTITY 与 Projections.distinct

于 2014-12-31T15:05:09.173 回答