NHibernate子查询关联表问题:获取最新版本记录的查询实现
QueryOver子查询获取最新版本+关联表解决方案
我看你已经在动手用NHibernate的QueryOver写获取SomeClass最新版本记录的子查询了,刚好写到SelectList的Se...就断了,我来帮你补全这个逻辑,顺便实现关联另一张表的完整查询。
首先先把你的实体类贴出来方便参考:
public class SomeClass { public virtual string KeyPart1 { get; set; } public virtual string KeyPart2 { get; set; } public virtual int VersionNo { get; set; } public virtual string ClassProperty1 { get; set; } public virtual string ClassProperty2 { get; set; } }
1. 补全获取最新版本的子查询
你的需求应该是按KeyPart1+KeyPart2这个复合键分组,拿到每组里最大的VersionNo(也就是最新版本),完整的子查询应该是这样:
var subquery = QueryOver.Of<SomeClass>() .SelectList(lst => lst .SelectGroup(sc => sc.KeyPart1) // 按KeyPart1分组 .SelectGroup(sc => sc.KeyPart2) // 按KeyPart2分组 .SelectMax(sc => sc.VersionNo) // 取每组最大的版本号 );
这个子查询会返回所有复合键对应的最新版本号集合,接下来用它过滤主查询。
2. 关联子查询+关联其他表的完整查询
假设你要关联的表是RelatedClass(比如和SomeClass通过KeyPart1+KeyPart2关联),我们可以用别名来简化关联逻辑:
// 定义查询别名,NHibernate QueryOver推荐用别名来避免歧义 SomeClass scAlias = null; RelatedClass rcAlias = null; var mainQuery = session.QueryOver(() => scAlias) // 用子查询过滤:只保留复合键和版本号匹配子查询结果的记录 .WithSubquery.WhereProperty(sc => new { sc.KeyPart1, sc.KeyPart2, sc.VersionNo }) .In(subquery) // 关联另一张表,这里假设关联条件是复合键匹配,你可以根据实际调整 .JoinAlias(() => scAlias.RelatedClass, () => rcAlias) // 如果你需要指定筛选条件,可以在这里加 .Where(() => rcAlias.IsActive == true) // 投影需要的字段,或者直接List<SomeClass>获取实体 .SelectList(lst => lst .Select(sc => sc.ClassProperty1) .Select(sc => sc.ClassProperty2) .Select(rc => rc.RelatedProperty1) ); // 执行查询,结果可以是object[]或者自定义DTO var results = mainQuery.List<object[]>();
备选:用Exists语法实现更高效的筛选
如果你的数据量较大,用Exists可能比In性能更好,子查询可以这么写:
var existsSubquery = QueryOver.Of<SomeClass>() .Where(sc => sc.KeyPart1 == scAlias.KeyPart1) .Where(sc => sc.KeyPart2 == scAlias.KeyPart2) .SelectMax(sc => sc.VersionNo) .Where(sc => sc.VersionNo == scAlias.VersionNo); var mainQuery = session.QueryOver(() => scAlias) .WithSubquery.WhereExists(existsSubquery) .JoinAlias(() => scAlias.RelatedClass, () => rcAlias);
这样就能精准拿到每个复合键对应的最新版本记录,同时关联上你需要的其他表了。
内容的提问来源于stack exchange,提问作者Nico Pizzo
相关产品推荐
相关产品推荐

