NHibernate QueryOver关联查询后仅获取Parent实体问题求助
嘿,我来帮你解决这个NHibernate的问题!当你用QueryOver做关联查询后,发现Parent实体的Children集合也被加载了,想要只拿到Parent本身的话,可以试试下面这几个实用的方法:
Not.Fetch明确排除关联集合加载 这是最直接的方式——告诉NHibernate,就算你做了Child的关联过滤,也别加载Parent的Children集合。示例代码如下:
Parent parentAlias = null; Child childAlias = null; var targetParents = session.QueryOver(() => parentAlias) .JoinAlias(() => parentAlias.Children, () => childAlias) // 关联Child表做条件过滤 .Where(() => childAlias.KeyPart1 == "你的过滤条件") // 替换成实际的查询条件 .Not.Fetch(() => parentAlias.Children).Eager // 强制不加载Children集合 .List<Parent>();
这里的Not.Fetch(...).Eager会让NHibernate返回的Parent里,Children是一个未初始化的代理集合(或者空集合,取决于你的映射),不会触发Child数据的查询。
如果你想更严格地控制返回内容,完全避免和Child实体的交互,可以用投影只提取Parent的字段,再组装成Parent实体。这样生成的SQL只会查询Parent的列,完全碰不到Child的数据:
Parent parentAlias = null; Child childAlias = null; var parentList = session.QueryOver(() => parentAlias) .JoinAlias(() => parentAlias.Children, () => childAlias) .Where(() => childAlias.KeyPart2 == "你的过滤条件") .SelectList(proj => proj .Select(() => parentAlias.KeyPart1) .Select(() => parentAlias.KeyPart2) .Select(() => parentAlias.KeyPart3) .Select(() => parentAlias.ParentProperty) ) .List<object[]>() .Select(result => new Parent { KeyPart1 = (string)result[0], KeyPart2 = (string)result[1], KeyPart3 = (string)result[2], ParentProperty = (string)result[3], Children = new HashSet<Child>() // 手动初始化空集合,避免代理问题 }) .ToList();
有时候问题出在实体映射上——如果你的Parent映射里给Children集合设置了非懒加载(比如Not.LazyLoad())或者Fetch.Join,那不管QueryOver怎么写,NHibernate都会自动加载Children。确认一下你的映射配置:
比如Fluent NHibernate的映射应该是这样的:
public class ParentMap : ClassMap<Parent> { public ParentMap() { // 映射主键和其他属性... HasMany(p => p.Children) .KeyColumns.Add("KeyPart1", "KeyPart2", "KeyPart3") .LazyLoad(); // 确保开启懒加载,默认就是,但最好明确设置 } }
如果之前设置了Not.LazyLoad(),改成LazyLoad()就能让Children默认只在需要的时候才加载。
如果你是想通过Child的条件过滤Parent(比如只返回有符合条件Child的Parent),同时又不想加载Child,方法1是最优解——它会生成带JOIN的SQL过滤Parent,但不会查询Child的字段,也不会初始化Children集合,完美平衡了过滤需求和性能。
内容的提问来源于stack exchange,提问作者Nico Pizzo

