nhibernate3查询-带集合的集合

nhibernate3查询-带集合的集合,nhibernate,fluent-nhibernate,nhibernate-mapping,Nhibernate,Fluent Nhibernate,Nhibernate Mapping,我的网页上有一些下拉列表。它们是链接的,具有类似的类结构和双向链接 换句话说:Alpha类有一个Beta类列表,而Beta类又有一个Charlie类列表。每个Beta类也有自己的Alpha列表(它所属的类),每个Charlie类也有自己的Beta列表 我正在使用NHibernate 3和流利的NHibernate和自动映射 现在。如果我只是简单地运行一个 session.CreateCriteria<Alpha>().SetMaxResults(1000).List<Alpha

我的网页上有一些下拉列表。它们是链接的,具有类似的类结构和双向链接

换句话说:Alpha类有一个Beta类列表,而Beta类又有一个Charlie类列表。每个Beta类也有自己的Alpha列表(它所属的类),每个Charlie类也有自己的Beta列表

我正在使用NHibernate 3和流利的NHibernate和自动映射

现在。如果我只是简单地运行一个

session.CreateCriteria<Alpha>().SetMaxResults(1000).List<Alpha>();

但是我该如何编写这个查询呢???

如果你使用条件,你需要包括方法调用。

如果你使用条件,你需要包括方法调用。

Ayende在他的博客中展示了一个很好的技巧。我没有亲自尝试过,因为我决定改变我的BL以避免这个问题,所以对此持保留态度


您应该能够单独加载集合,并让NHibernate使用NHibernate连接实体。因为这不是一个轻松的话题,所以最好是你。

Ayende在他的博客中展示了一个很好的技巧。我没有亲自尝试过,因为我决定改变我的BL以避免这个问题,所以对此持保留态度


您应该能够单独加载集合,并让NHibernate使用NHibernate连接实体。因为它不是一个轻松的主题,所以最好是您。

据我所知,您无法像连接获取一样,在逐级查询中提供帮助。但是,如果更改映射并将关联的默认获取模式设置为子查询,您可能会感到惊喜:

从与NHibernate同样出色的作品中:

在集合上使用fetch=subselect,您可以告诉Hibernate不要只加载此集合 在第二个集合中选择lazy或non-lazy,但也选择所有其他集合 对于在第一个选择中加载的所有拥有实体。这对其他人特别有用 并行获取多个集合

这意味着,当需要第一个关联时,NHibernate将调用用于获取根实体的查询,而不是加载一个关联,然后加载查询返回的根实体类型的所有实例的关联数据

也就是说,如果你正在加载1K个实体,并且你希望每个关联都有多个记录,那么你可能会从一个选择的N+1^2变成一个我刚刚将整个数据库加载到内存中的垃圾-


注意,如果您这样做,并且有一个场景,您加载Alpha列表,但只需要单个Alpha的相关beta,那么您仍然将加载所有beta,对此您无能为力。但在实践中,我发现这是一种非常罕见的情况,因此通常子选择获取非常适合我。

据我所知,在查询级别上,您无法像连接获取那样对此有所帮助。但是,如果更改映射并将关联的默认获取模式设置为子查询,您可能会感到惊喜:

从与NHibernate同样出色的作品中:

在集合上使用fetch=subselect,您可以告诉Hibernate不要只加载此集合 在第二个集合中选择lazy或non-lazy,但也选择所有其他集合 对于在第一个选择中加载的所有拥有实体。这对其他人特别有用 并行获取多个集合

这意味着,当需要第一个关联时,NHibernate将调用用于获取根实体的查询,而不是加载一个关联,然后加载查询返回的根实体类型的所有实例的关联数据

也就是说,如果你正在加载1K个实体,并且你希望每个关联都有多个记录,那么你可能会从一个选择的N+1^2变成一个我刚刚将整个数据库加载到内存中的垃圾-


注意,如果您这样做,并且有一个场景,您加载Alpha列表,但只需要单个Alpha的相关beta,那么您仍然将加载所有beta,对此您无能为力。但在实践中,我发现这是一种非常罕见的情况,因此通常子选择获取非常适合我。

Alpha和Beta、Beta和Charlie之间存在双向关系-您怎么能期望只查询这三个表?必须有链接表来实现这一点…哦,愚蠢的我,你是绝对正确的!我会更新文本。听起来你在使用无状态会话。无状态会话没有缓存,并且无状态会话中的对象不能延迟加载。这意味着您将无法预取组件并执行复合查询。如果是这种情况,则需要使用.Fetch输入查询,以便急切地从Alpha2Beta和Beta2Charlie加载子对象。你仍然会有一些重复-bu

没有N+1那么糟糕。在Alpha和Beta、Beta和Charlie之间存在双向关系-您怎么能期望只查询这三个表?必须有链接表来实现这一点…哦,愚蠢的我,你是绝对正确的!我会更新文本。听起来你在使用无状态会话。无状态会话没有缓存,并且无状态会话中的对象不能延迟加载。这意味着您将无法预取组件并执行复合查询。如果是这种情况,则需要使用.Fetch输入查询,以便急切地从Alpha2Beta和Beta2Charlie加载子对象。您仍然会有一些重复,但没有N+1那么糟糕。据我所知,您不能在多个集合上使用动态抓取。您可以通过这种方式获取多个相关实体和一个集合。据我所知,您不能对多个集合使用动态获取。您可以通过这种方式获取多个相关实体和一个集合。这种方式会起作用,但即使您查询每个Alpha和每个Beta,您仍会遇到SELECT N+1,因为NH必须查询Alpha-Beta关联。同样,我没有尝试它,只是指向资源,但是,如果同时加载Alpha和Beta以及join表,为什么还需要另一个N+1呢?我不是说加载所有东西都可以,但如果不行,那是因为它不受支持,而不是因为它无法实现。当然,这需要一些创造性的映射:映射联接表如果查询Alpha和beta,identity-map一级缓存将确保在访问Alpha中的关联时不需要加载任何beta。但是,查询中没有加载的是关联表的内容,因此,当您点击关联时,会发生从Alpha_到β的选择,其中Alpha_Id=n,而不是从Alpha_到β的选择内部连接β…-也就是说,如果关联尚未加载,那么预加载实体本身也无济于事。这是否澄清了我的观点-我完全理解你的意思,但这不是我所说的:我是说,在数据表Alpha、Beta旁边将关联表Alpha_映射到Beta是值得的,并将所有3个表加载到它们最完整的NHibernate!可能会使用加载的Alpha-to-Beta表来连接实体。我不打算再为这个“可能”的场景辩护了,我试图为这是可能的原则辩护。对,好的。我仍然认为你链接的文章中的技术不会做到这一点——它在示例中起作用,因为Post-User关联是1..1,但它不会与1..*一起工作。或者更确切地说,它会,但它仍然是选择N+1-这在某种程度上是可行的,但即使你查询每个Alpha和每个Beta,你仍然会遇到一个SELECT N+1,因为NH必须查询Alpha-Beta关联。再说一次,我没有尝试它,只是指向资源,但如果你同时加载Alpha和Beta并加入表,为什么还需要另一个N+1呢?我不是说加载所有东西都可以,但如果不行,那是因为它不受支持,而不是因为它无法实现。当然,这需要一些创造性的映射:映射联接表如果查询Alpha和beta,identity-map一级缓存将确保在访问Alpha中的关联时不需要加载任何beta。但是,查询中没有加载的是关联表的内容,因此,当您点击关联时,会发生从Alpha_到β的选择,其中Alpha_Id=n,而不是从Alpha_到β的选择内部连接β…-也就是说,如果关联尚未加载,那么预加载实体本身也无济于事。这是否澄清了我的观点-我完全理解你的意思,但这不是我所说的:我是说,在数据表Alpha、Beta旁边将关联表Alpha_映射到Beta是值得的,并将所有3个表加载到它们最完整的NHibernate!可能会使用加载的Alpha-to-Beta表来连接实体。我不打算再为这个“可能”的场景辩护了,我试图为这是可能的原则辩护。对,好的。我仍然认为你链接的文章中的技术不会做到这一点——它在示例中起作用,因为Post-User关联是1..1,但它不会与1..*一起工作。或者更确切地说,它会,但它仍然是选择N+1-
select top 1000 * from Alpha
select top 1000 * from Beta
select top 1000 * from Charlie
select * from Alpha2Beta
select * from Beta2Charlie