NHibernate:如何用Query<>查询并获取子类中的关联对象
NHibernate Table-Per-Subclass 下用LINQ Query<>预加载子类关联属性的解决方案
针对基类Element、子类Material(关联Category)和Operational(关联EnergySource)的table-per-subclass配置,以下是用LINQ Query<>实现预加载子类特有关联属性的可行方案:
1. 单独查询单个子类并预加载关联
如果只需要查询某一个子类的实例,直接用OfType<>筛选子类后,结合Fetch即可生成正确的SQL关联查询:
// 查询Material子类并预加载Category关联 var materials = session.Query<Element>() .OfType<Material>() .Fetch(m => m.Category) .ToList(); // 查询Operational子类并预加载EnergySource关联 var operationals = session.Query<Element>() .OfType<Operational>() .Fetch(o => o.EnergySource) .ToList();
这种方式会自动关联子类表和对应的关联表,避免N+1查询。
2. 同时查询多个子类并预加载各自关联
如果需要一次性获取所有Element子类实例,并分别预加载它们的特有关联,可以通过投影方式实现:
var elements = session.Query<Element>() // 若基类有公共关联,可先预加载 // .Fetch(e => e.CommonAssociation) .Select(e => new { Element = e, // 针对Material子类的Category关联 MaterialCategory = e is Material ? ((Material)e).Category : null, // 针对Operational子类的EnergySource关联 OperationalEnergy = e is Operational ? ((Operational)e).EnergySource : null }) .ToList() // 提取原始Element实例,此时关联属性已被预加载 .Select(x => x.Element) .ToList();
NHibernate会将该查询转换为包含基类表、两个子类表以及对应关联表的左连接SQL,一次性加载所有需要的数据。
关键注意事项
- 必须通过类型筛选(
OfType<>)或类型转换明确告知NHibernate要访问的子类属性,直接在基类Query<>中引用子类属性会导致无法转换为SQL的错误。 - 确保table-per-subclass的映射配置正确:子类使用
<joined-subclass>节点,<many-to-one>关联配置符合NHibernate规范。
内容的提问来源于stack exchange,提问作者Lovethenakedgun
相关产品推荐
相关产品推荐

