[英]How to translate 'where not in' into an NHibernate query where the subquery table is not an entity?
我有兩個實體: User
和Notice
,它們通過連接在一起DismissedNoticeToUser
表( UserId
和NoticeId
是各自列)。
這是我的User
類的 FluentNHibernate 映射:
mapping.HasManyToMany<Notice>(u => u.DismissedNotices)
.Table("DismissedNoticeToUser")
.ParentKeyColumn("UserId")
.ChildKeyColumn("NoticeId")
.Inverse();
每次使用“駁回”的通知,一對的User.Id
和Notice.Id
添加到DismissedNoticeToUser
類。 這在代碼中很容易:
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。
我認為以下帖子描述了如何查詢這些多對多關系:
可能還有很多其他類似的帖子。
這是一個更接近您要求的示例:
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>();
如果您無法將 Users 映射到 Notice,也可以嘗試針對 Query 編寫 Query 代碼。 我還沒有嘗試過與 Load to Query 合作,對 Query 使用 Load 可能會導致 NH 生成單獨的查詢。
試試這個:
this.session.Query<Notice>().Where( n =>
this.session.Query<User>().Any(u => u.UserId == "007"
&& !u.DismissedNotices.Contains(n) );
嗨,我為您的示例通知和 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”和“id”是來自實體的主鍵列的名稱,而不是來自 db。 我沒有完全測試你的情況,總線非常相似的東西對我來說完美無缺。
你快到了,將包含更改為任何:
string userId = "007";
this.session.Query<Notice>().Where( n =>
!n.Users.Any(x => x.UserId == userId) );
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.