如何翻译';其中not在';转换为NHibernate查询,其中子查询表不是实体
本文关键字:查询 实体 查询表 NHibernate 翻译 何翻译 其中 转换 not | 更新日期: 2023-09-27 18:26:49
我有两个实体:User
和Notice
,它们通过DismissedNoticeToUser
表链接在一起(UserId
和NoticeId
分别是列)。
以下是我为User
类绘制的FluentHibernate映射:
mapping.HasManyToMany<Notice>(u => u.DismissedNotices)
.Table("DismissedNoticeToUser")
.ParentKeyColumn("UserId")
.ChildKeyColumn("NoticeId")
.Inverse();
每次使用"驳回"通知时,都会向DismissedNoticeToUser
类中添加一对User.Id
和Notice.Id
。这在代码中很容易:
var notice = this.session.Load<Notice>(noticeId);
var user = this.session.Load<User>(this.userSession.Id);
user.DismissedNotices.Add(notice);
如果我想列出所有被用户驳回的而不是的通知,我会在原始SQL:中写这样的东西
select * from [Notice]
where Id not in
(select NoticeId from [DismissedNoticeToUser] where UserId=@userId)
然而,我真的不知道如何使用NHibernate来做同样的事情。我已经尝试了以下操作,但它在用户的通知中作为单独的查询执行左联接。
this.session.Query<Notice>().Where(n => !user.DismissedNotices.Contains(n));
我可以放下并使用NHibernate来编写原始SQL,但我觉得我可能遗漏了一些东西。我不在乎我使用哪一个NHibernate查询API。
如果不能将Users映射到Notice,也可以根据Query编写Query。我还没有尝试将Load与Query合作,对Query使用Load可能会导致NH生成单独的查询。
试试这个:
this.session.Query<Notice>().Where( n =>
this.session.Query<User>().Any(u => u.UserId == "007"
&& !u.DismissedNotices.Contains(n) );
我认为下面的帖子描述了如何查询这些多对多关系:
FluentHibernate对多对多关系对象的查询
可能还有很多其他类似的帖子也有这种效果。
编辑
以下是一个更接近您要求的示例:
var subquery = QueryOver.Of<Notice>()
.JoinQueryOver<User>(x => x.DismissedNotices)
.Where(x => x.Id == userId)
.Select(x => x.Id);
IList<Notice> groupsFound =
session.QueryOver<Notice>()
.WithSubquery.WhereProperty(x => x.Id).NotIn(subquery)
.List<Notice>();
如果您想生成与上面完全相同的查询,我不确定您能否做到这一点,除非您将表DismissedNoticeToUser
映射为一个实体。如果你要这样做,那么你可能会做这样的事情:
var subquery = QueryOver.Of<DismissedNoticeToUser>()
.Where(x => x.UserId == userId)
.Select(x => x.NoticeId);
IList<Notice> noticesFound = session.QueryOver<Notice>()
.WithSubquery.WhereProperty(x => x.Id).NotIn(subquery)
.List<Notice>();
您差不多到了,将Contains更改为Any:
string userId = "007";
this.session.Query<Notice>().Where( n =>
!n.Users.Any(x => x.UserId == userId) );
嗨,我为您的示例Notice和DismissedNoticeToUser实体制作了它。
var userIdParam = 111;
var results = session.GetSession().CreateCriteria(typeof(Notice));
var notInSubQuery = DetachedCriteria.For<DismissedNoticeToUser>()
.Add(Expression.Eq("userId", userIdParam))
.SetProjection(NHibernate.Criterion.Projections.Id());
results.Add(Subqueries.PropertyNotIn("id",notInSubQuery));
var result = results.List<Notice>();
注意,"userId"answers"id"是来自实体的主键列的名称,而不是来自数据库的。我并没有完全测试你的情况,公交车上类似的东西对我来说效果很好。