如何在Nhibernate上对子集合执行QueryOver

您好我有一个名为Notifications的类,它是User的子类。

public class User { public int Id { get; set; } public string Name { get; set; } public string UserName { get; set; } public ICollection UserNotifications { get; set; } } public class Notification { public int Id { get; set; } public ICollection UserNotifications { get; set; } public string Title { get; set; } public string Message { get; set; } public bool IsRead { get; set; } public DateTime CreatedDate { get; set; } } public class UserNotification { public User User { get; set; } public Notification Notification { get; set; } } 

现在我想获得User By ID,它将为当前用户带来所有通知。

 var user = NhSession.Get(userId); 

但我不想收到所有通知。 我只想让用户收到未读通知,只想为用户获得top 5 (Latest) notifications

我尝试通过joinQueryOver实现这一点,但我无法做到这一点。 任何人都可以建议让这个工作。

基于最新的更新和新的Entity(ies)结构,我们现在可以从Pairing对象中获利,并快速选择具有未读Notificaitons的用户

查找尚未阅读通知的用户

 var session = NHSession.GetCurrent(); Notification notification = null; UserNotification pair = null; User user = null; var subquery = QueryOver.Of(() => pair) // this will give us access to notification // see we can filter only these which are NOT read .JoinQueryOver(() => pair.Notification, () => notification) // here is the filter .Where(() => !notification.IsRead) // now the trick to take only related to our user .Where(() => pair.User.Id == user.Id) // and get the user Id .Select(x => pair.User.Id); var listOfUsers = session.QueryOver(() => user) .WithSubquery .WhereProperty(() => user.Id) .In(subquery) // paging .Take(10) .Skip(10) .List(); 

每个userId查找5个未读通知

 var userId = 1; var subqueryByUser = QueryOver.Of(() => pair) // now we do not need any kind of a join // just have to filter these pairs related to user .Where(() => pair.User.Id == userId) // and get the notification Id .Select(x => pair.Notification.Id); var notificationsPerUser = session.QueryOver(() => notification) .WithSubquery .WhereProperty(() => notification.Id) .In(subqueryByUser) .Where(() => !notification.IsRead) // if needed we can order // .OrderBy(... .Take(5) .List() 

session.Get(entityId)是我们加载实体AS IS映射的。 这是合同。

如果我们想要获得过滤结果,我们必须使用另一个合同来重新获取数据: Session.CreateCriteria() (或任何其他查询API,即QueryOver()

所以在我们的例子中,我们应该构建查询以查找具有未读通知的用户:

 Occupation Notification= null; User user = null; var subquery = QueryOver.Of(() => notification) .Where(() => !notification.IsRead ) // just related to the user, from outer query .Where(() => notification.User.ID == user.ID) .Select(x => notification.User.ID); var list = session.QueryOver(() => user) .WithSubquery .WhereProperty(() => user.ID) .In(subquery) // paging .Take(10) .Skip(10) .List(); 

我们在这里可以看到的是,通知(通常是必须的)通知已向用户反馈其父级:

 public class Notification { ... public User User {get;set;} } 

但这应该不是问题,它只是一个映射,而不是DB的变化

类似的查询(在通知之上)我们可以使用它们只获得前5个:

 var notifications = session.QueryOver(() => notification) // here is a userId for a specific user. // we can use IN() to load for more of them .Where(() => notification.User.ID != userId) .Take(5) .List() ;