反转NHibernate查询的逻辑

反转NHibernate查询的逻辑,nhibernate,nhibernate-criteria,Nhibernate,Nhibernate Criteria,我使用NHibernate构建了以下查询,它将为我提供一个MenuView项的集合,这些项包含给定的页面(由页面id引用) 它仍然返回确实包含id为8的页面的菜单项的结果。为什么这种简单的逻辑反转在代码方面不是那么简单 [更新] 采纳Firo的建议,将建议的查询更改为 // Only retrieve menus that do NOT contain this referenced page .CreateCriteria("Pages") .Add(Subqueries.PropertyNo

我使用
NHibernate
构建了以下查询,它将为我提供一个
MenuView
项的集合,这些项包含给定的页面(由页面id引用)

它仍然返回确实包含id为8的页面的菜单项的结果。为什么这种简单的逻辑反转在代码方面不是那么简单

[更新] 采纳Firo的建议,将建议的查询更改为

// Only retrieve menus that do NOT contain this referenced page
.CreateCriteria("Pages")
.Add(Subqueries.PropertyNotIn("Id", querymenuItemswithPage))   <--- query you have would be here
)

一开始这似乎正是我想要的,但遗憾的是(可能是因为我对连接的理解不好)仍然没有返回我想要的。根据下表

菜单

然后是PagesInMenu的联接表(带有WHERE PageID=1的WHERE子句)

我们可以看到,id为1的页面未在菜单5和6中引用。我希望相关查询只返回一行,即ID为5的菜单的ID、名称和说明,因为这是唯一一个第1页未包含且可编辑的菜单

相反,新查询返回

我已经划掉了所有返回但不应该返回的行。这是怎么回事

更新:

  • 已删除
    .CreateCriteria(“页面”)
  • 添加子查询

    var querymenuItemswithPage = DetachedCriteria.For<Menu>()
    .CreateCriteria("Pages")
        .Add(Restrictions.Eq("ID", pageId))
    .SetProjection(Projections.Id())
    
    // Only retrieve the required properties from Menu object
    ProjectionList menuViewProjections = Projections.ProjectionList()
        .Add(Projections.Property("ID"), "ID")
        .Add(Projections.Property("Name"), "Name")
        .Add(Projections.Property("Description"), "Description");
    
    var menus = session.CreateCriteria(typeof(Menu))
        // Only menu's that are editable
        .Add(Restrictions.Eq("IsEditable", true))
    
        // Only project required properties
        .SetProjection(menuViewProjections)
    
        // Only retrieve menus that do NOT contain this referenced page
        .Add(Subqueries.PropertyNotIn("Id", querymenuItemswithPage))
    
        // Transform results into required view objects
        .SetResultTransformer(Transformers.AliasToBean(typeof(MenuView)))
        .List<MenuView>();
    
    var querynumitemswithpage=DetachedCriteria.For()
    .CreateCriteria(“页面”)
    .Add(Restrictions.Eq(“ID”,pageId))
    .SetProjection(Projections.Id())
    //仅从菜单对象检索所需的属性
    ProjectionList菜单视图投影=投影。ProjectionList()
    .Add(Projections.Property(“ID”),“ID”)
    .Add(Projections.Property(“名称”),“名称”)
    .添加(投影、属性(“说明”)、“说明”);
    var menus=session.CreateCriteria(菜单类型))
    //只有可编辑的菜单
    .Add(Restrictions.Eq(“IsEditable”,true))
    //仅项目所需的属性
    .SetProjection(菜单视图投影)
    //仅检索不包含此引用页面的菜单
    .Add(subquerys.PropertyNotIn(“Id”,querynumitemswithpage))
    //将结果转换为所需的视图对象
    .SetResultTransformer(Transformers.AliasToBean(typeof(MenuView)))
    .List();
    

因为它是从“页面中的一项符合条件”更改为“页面中的所有项符合条件”,所以“限制”对象上没有.Property这样的东西。有些东西像EqProperty、LeProperty、GtProperty等,但没有一个是以字符串作为参数的。感谢将此问题向前推进一点,请参阅编辑信息我已更新了我的答案,我忘记排除creatcriteria(页面)非常感谢!此查询现在可以按预期工作。万岁,菲罗。
SELECT this_.ID          as y0_,
   this_.Name        as y1_,
   this_.Description as y2_
FROM   [Menu] this_
       inner join PagesInMenu pages3_
         on this_.ID = pages3_.MenuID
       inner join [Page] page1_
         on pages3_.PageID = page1_.ID
WHERE  this_.IsEditable = 1 /* @p0 */
       and not (page1_.ID = 8 /* @p1 */)
// Only retrieve menus that do NOT contain this referenced page
.CreateCriteria("Pages")
.Add(Subqueries.PropertyNotIn("Id", querymenuItemswithPage))   <--- query you have would be here
    SELECT this_.ID          as y0_,
       this_.Name        as y1_,
       this_.Description as y2_
FROM   [Menu] this_
       inner join PagesInMenu pages3_
         on this_.ID = pages3_.MenuID
       inner join [Page] page1_
         on pages3_.PageID = page1_.ID
WHERE  this_.IsEditable = 1 /* @p0 */
       and page1_.ID not in (SELECT this_0_.ID as y0_
                             FROM   [Page] this_0_
                             WHERE  this_0_.ID = 1 /* @p1 */
var querymenuItemswithPage = DetachedCriteria.For<Menu>()
.CreateCriteria("Pages")
    .Add(Restrictions.Eq("ID", pageId))
.SetProjection(Projections.Id())

// Only retrieve the required properties from Menu object
ProjectionList menuViewProjections = Projections.ProjectionList()
    .Add(Projections.Property("ID"), "ID")
    .Add(Projections.Property("Name"), "Name")
    .Add(Projections.Property("Description"), "Description");

var menus = session.CreateCriteria(typeof(Menu))
    // Only menu's that are editable
    .Add(Restrictions.Eq("IsEditable", true))

    // Only project required properties
    .SetProjection(menuViewProjections)

    // Only retrieve menus that do NOT contain this referenced page
    .Add(Subqueries.PropertyNotIn("Id", querymenuItemswithPage))

    // Transform results into required view objects
    .SetResultTransformer(Transformers.AliasToBean(typeof(MenuView)))
    .List<MenuView>();