NHibernate 5.x Criteria API如何查询未关联Study的Episode数据
嗨,这个问题我刚好有类似的处理经验,咱们来一步步搞定它!
首先得理清现在的表关系变化:原来Episode表有直接关联Study的字段,现在外键移到了Study表的id_episode列,变成了**Episode(一)对应Study(多)**的关系——也就是说,一个Episode可以被多个Study引用,而我们要找的是完全没有被任何Study引用的Episode行。
原来的Expression.IsNull("Study")之所以失效,是因为Episode实体里已经没有这个单值的Study属性了,现在得换两种思路来实现:
方法一:左外连接+空值过滤
通过左外连接把Episode和它关联的Study数据拉出来,然后过滤掉那些有Study关联的记录,剩下的就是没有关联的Episode。具体代码如下:
using NHibernate.Criterion; using NHibernate.SqlCommand; // 创建Episode的查询Criteria var criteria = sess.CreateCriteria<Episode>("episode") // 左外连接到Study关联(这里假设Episode实体有一个名为Studies的集合属性) .CreateAlias("episode.Studies", "study", JoinType.LeftOuterJoin) // 过滤关联Study不存在的情况(即Study的主键为null) .Add(Restrictions.IsNull("study.Id"));
这里关键是JoinType.LeftOuterJoin——如果用默认的内连接,只会返回有Study关联的Episode,左外连接才能保留所有Episode,不管有没有关联的Study,再通过IsNull("study.Id")筛选出没有关联的那些。
方法二:子查询排除法
另一种更直观的思路是:找出所有id不在Study表id_episode字段中的Episode。用DetachedCriteria来写子查询,代码如下:
using NHibernate.Criterion; // 先定义子查询:获取所有存在关联的Episode的id(即Study表中所有的id_episode值) var subquery = DetachedCriteria.For<Study>() .SetProjection(Projections.Property("IdEpisode")); // 主查询:筛选Episode的id不在子查询结果中的记录 var criteria = sess.CreateCriteria<Episode>("episode") .Add(Subqueries.PropertyNotIn("episode.Id", subquery));
这种写法逻辑更直白,直接表达“排除掉所有被Study引用过的Episode”,适合对关联关系理解更清晰的场景。
你可以根据自己实体类的映射情况(比如Episode的集合属性名称是不是Studies)调整代码里的属性名,测试一下就能得到想要的结果啦!
备注:内容来源于stack exchange,提问作者anddam

