簡體   English   中英

如何將“where not in”轉換為子查詢表不是實體的 NHibernate 查詢?

[英]How to translate 'where not in' into an NHibernate query where the subquery table is not an entity?

我有兩個實體: UserNotice ,它們通過連接在一起DismissedNoticeToUser表( UserIdNoticeId是各自列)。

這是我的User類的 FluentNHibernate 映射:

mapping.HasManyToMany<Notice>(u => u.DismissedNotices)
    .Table("DismissedNoticeToUser")
    .ParentKeyColumn("UserId")
    .ChildKeyColumn("NoticeId")
    .Inverse();

每次使用“駁回”的通知,一對的User.IdNotice.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。

我認為以下帖子描述了如何查詢這些多對多關系:

FluentNHibernate 查詢多對多關系對象

可能還有很多其他類似的帖子。

編輯

這是一個更接近您要求的示例:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM