NHibernate 分页标准与 fetchmode eager。 (使用流动的NH)
问题:如何获取急切加载的条件以在根实体上返回分页结果,并将所有子集合设置为 fetchmode = eager。
我正在尝试获取包含 10 项的分页结果集,其中包含急切加载的子集合。问题是查询在整个选择周围选择了前 10 个。这会导致它仅返回前 10 个结果,包括所有连接的记录。如果第一个实体有 10 个子对象,那么我的结果集将返回 1 个加载了 10 个子对象的实体。我需要返回水合的实体和子集合(懒惰)。如果我关闭延迟加载并运行此查询,我会得到结果集中每个关联的 n+1 查询。
这是我的基本查询过程:
criteria = context.Session.CreateCriteria<Associate>();
criteria.SetMaxResults(10); //hardcoded for testing
criteria.SetFirstResult(1); //hardcoded for testing
criteria.SetFetchMode("Roles", NHibernate.FetchMode.Eager);
criteria.SetFetchMode("Messages", NHibernate.FetchMode.Eager);
criteria.SetFetchMode("DirectReports", NHibernate.FetchMode.Eager);
criteria.SetResultTransformer(new DistinctRootEntityResultTransformer());
return criteria.List<Associate>();
public AssociateMap()
{
ReadOnly();
Id(x => x.AssociateId);
Map(x => x.FirstName);
Map(x => x.LastName);
Map(x => x.ManagerId);
Map(x => x.Department);
Map(x => x.Email);
Map(x => x.JobTitle);
Map(x => x.LastFirstName).Formula("LTRIM(RTRIM(LastName)) + ', ' + LTRIM(RTRIM(FirstName))");
HasMany(x => x.Messages).KeyColumn("AssociateId").Inverse().Cascade.All();
HasMany(x => x.Roles).Element("RoleKey");
HasMany(x => x.DirectReports).KeyColumn("ManagerId").Cascade.None().ForeignKeyConstraintName("FK_Associate_Manager");
//HasMany(x => x.DirectReports).Element("ManagerId").CollectionType(typeof(Domain.Associate));
}
Question: How to get an eager loaded criteria to return paged results on the root entity with all child collections set fetchmode = eager.
I am trying to get a 10 item paged result set with eager loaded child collections. The problem is the query does a select top 10 wrapped around the entire select. The causes it to return only the first 10 results including all joined records. If the first entity has 10 child objects then my result set will return 1 entity with 10 child objects loaded. I need the entities and child collections returned hydrated (lazy off). If I turn lazy loading off and run this query I get the n+1 query for each associate in result set.
This is my basic query process:
criteria = context.Session.CreateCriteria<Associate>();
criteria.SetMaxResults(10); //hardcoded for testing
criteria.SetFirstResult(1); //hardcoded for testing
criteria.SetFetchMode("Roles", NHibernate.FetchMode.Eager);
criteria.SetFetchMode("Messages", NHibernate.FetchMode.Eager);
criteria.SetFetchMode("DirectReports", NHibernate.FetchMode.Eager);
criteria.SetResultTransformer(new DistinctRootEntityResultTransformer());
return criteria.List<Associate>();
public AssociateMap()
{
ReadOnly();
Id(x => x.AssociateId);
Map(x => x.FirstName);
Map(x => x.LastName);
Map(x => x.ManagerId);
Map(x => x.Department);
Map(x => x.Email);
Map(x => x.JobTitle);
Map(x => x.LastFirstName).Formula("LTRIM(RTRIM(LastName)) + ', ' + LTRIM(RTRIM(FirstName))");
HasMany(x => x.Messages).KeyColumn("AssociateId").Inverse().Cascade.All();
HasMany(x => x.Roles).Element("RoleKey");
HasMany(x => x.DirectReports).KeyColumn("ManagerId").Cascade.None().ForeignKeyConstraintName("FK_Associate_Manager");
//HasMany(x => x.DirectReports).Element("ManagerId").CollectionType(typeof(Domain.Associate));
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
该解决方案最终使用子查询来设置最大结果。我使用 Subqueries.PropertyIn 添加了子查询。我将“条件”克隆为“限制器”,因为我在未显示的代码中添加了条件表达式。因此,我需要将这些条件克隆到子查询中,以便前 10 个选择将位于“IN”语句中。现在,我可以立即加载子集合并向根实体添加分页以获取 10 个实体,而不会出现笛卡尔或 n+1 的问题。我将尝试跟进更完整、更有组织的代码。
The solution ended up using a subquery to set the max results. I added the subquery using Subqueries.PropertyIn. I am cloning the "criteria" to "limiter" because I added criterion expression in code not shown. So I need to clone these criterion into the subquery so the top 10 select will be in the "IN" statement. Now I can eager load the child collections and add pagination to the root entity to get 10 enties back without issues with cartesian or n+1. I will try to follow up with more complete and organized code.