NHibernate iStatelessSession 在急切获取时返回重复的父实例

标签 nhibernate fluent-nhibernate fetch eager istatelesssession

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

解决
.TransformUsing(new DistinctRootEntityResultTransformer()) 

但对于 IStatelessSession 则不是。

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

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

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

最佳答案

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

13.2. The StatelessSession interface

Alternatively, NHibernate provides a command-oriented API that may be used for streaming data to and from the database in the form of detached objects. A IStatelessSession has no persistence context associated with it and does not provide many of the higher-level life cycle semantics. In particular, a stateless session does not implement a first-level cache nor interact with any second-level or query cache. It does not implement transactional write-behind or automatic dirty checking. Operations performed using a stateless session do not ever cascade to associated instances. Collections are ignored by a stateless session. Operations performed via a stateless session bypass NHibernate's event model and interceptors...

我只是试着在这里解释一下: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

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

  • 标准 session ,不使用(让它立即处理)
  • 加载根实体(Parent)列表
  • 让 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. Using batch fetching

NHibernate can make efficient use of batch fetching, that is, NHibernate can load several uninitialized proxies if one proxy is accessed (or collections. Batch fetching is an optimization of the lazy select fetching strategy. There are two ways you can tune batch fetching: on the class and the collection level.

Batch fetching for classes/entities is easier to understand. Imagine you have the following situation at runtime: You have 25 Cat instances loaded in an ISession, each Cat has a reference to its Owner, a Person. The Person class is mapped with a proxy, lazy="true". If you now iterate through all cats and call cat.Owner on each, NHibernate will by default execute 25 SELECT statements, to retrieve the proxied owners...

父映射应该是这样的:

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

请同时检查这些:

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

关于NHibernate iStatelessSession 在急切获取时返回重复的父实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27722725/

相关文章:

c# - 使用 where 语句的 Linq to NHibernate 包装器问题

c# - Windows 服务看不到文件

javascript - res.render() 和 res.redirect() 的行为类似于 res.send()

javascript - 服务 worker : No FetchEvent for javascript triggered request?

nhibernate - 如何配置 FluentNHibernate 不覆盖现有的 SQLite 数据库文件?

javascript - 错误 : SyntaxError: Unexpected end of JSON input at fetch. then.response

nhibernate - NHibernate中的SQL 2008 HierarchyID支持

.net - 无法将表达式类型 'NHibernate.IQueryOver<T,T>' 转换为返回类型 'System.Linq.IQueryable<T>'

nhibernate - 在具有不同列名的不同表上使用 ICompositeUserType

c# - 如何使用列表和关系对象测试 fluent-NHibernate 的 PersistenceSpecification.VerifyTheMappings?