我已经使用NHibernate
构建了以下查询,它将为我提供包含给定页面(由页面id引用)的MenuView
项目的集合。颠倒NHibernate查询的逻辑
// 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 menu's that contain this page (Menu object has IList<Page> property called 'Pages')
.CreateCriteria("Pages")
// Restrict to menu's containing the pages with an id of the specified value
.Add(Restrictions.Eq("ID", pageId))
// Transform results into required, light-weight, view objects
.SetResultTransformer(Transformers.AliasToBean(typeof(MenuView)))
.List<MenuView>();
这工作正常;然而,现在我想做相反的事情:我想查询所有可编辑菜单对象,其中不包含包含具有指定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
.CreateCriteria("Pages")
.Add(Restrictions.Not(Restrictions.Eq("ID", pageId)))
// Transform results into required view objects
.SetResultTransformer(Transformers.AliasToBean(typeof(MenuView)))
.List<MenuView>();
但是,这会导致下面的SQL:
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 */)
这仍然是返回菜单的结果做的项目包含一个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
现在生成下面的sql语句;
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 */
)
起初似乎正是我想要的,但不幸的是(可能是由于我加入的理解差)仍然没有回来完全是我想要的。给出下面的表
菜单
然后的PagesInMenu联接表(具有WHERE子句WHERE PAGEID = 1)
我们可以看到ID为1的页面在菜单5和6中没有被引用。我期待有问题的查询仅返回单行,这将是编号,姓名,并用5号菜单的说明,因为这是第1页是不列入和是编辑
相反,只有菜单新的查询返回;
我已经越过了被返回,但不应该成为所有行。这里发生了什么 !?
,因为它从一个变化 “一项在网页符合条件”,以“在页面比赛的所有项目条件“ – Firo 2012-01-03 13:01:14