如何使用NHibernate QueryOver进行“not in”查询?

4

有没有一种方式可以使用NHibernate更轻松地创建此查询?

为了理解,这是我想要使用NHibernate创建的查询:

Select * from Task
Where task_id not in
(Select task_id from UserTask
Where solved = 1 AND [user_id] = 1)

这是我用NHibernate编写的C#代码:

public IList<Task> RandomTasks(List<int> subject_ids, int userId)
{
    //Gets all Ids where the User has solved the Task
    List<int> task_ids = new List<int>(_session.Query<UserTask>()
                       .Where(x => x.User.user_id == userId)
                       .Where(x => x.solved)
                       .Select(x => x.Task.task_id));

    //Gets all Tasks except the task_ids from the result of the query befor
    var query = _session.QueryOver<Task>()
                       .Where(s => s.Subject.subject_id.IsIn(subject_ids))
                       .Where(t => !t.task_id.IsIn(task_ids))
                       .Take(10)
                       .List();

    return query;
}

这个查询返回了正确的结果,但我认为可能有更简单的方法来得到相同的结果。

2个回答

1
如果您更喜欢使用INNER SELECT,NHiberante为您提供了解决方案。它被称为DetachedCriteria。(请尝试查看此处以获取类似示例)
首先,我们将创建内部选择:
var sub = DetachedCriteria
  .For<UserTask>()
  // WHERE 
  .Add(Restrictions.In("UserId", new int[] { 1, 2 })) // example of filtering 'user_id'
  .Add(Restrictions.Eq("solved", true))               // 'solved'
  .SetProjection(Projections.Property("TaskId")); // TaskId the SELECT clause

我不确定你的模型和命名方式,例如task_id vs TaskId...但意图应该是清晰的。

使用DetachedCriteria我们可以做很多事情,我们可以连接其他引用的对象/表,对它们进行过滤...就像使用标准的QueryOver一样。唯一的区别在于,我们应该返回Projection(SELECT TaskId)作为另一个查询中的过滤器:

var criteria = session.CreateCriteria<Task>();
criteria
  . Where(...                             // your filters applied on Task
  .Add(Subqueries.PropertyIn("ID", sub)); // Task.ID in (select...

变量result等于criteria.List();

注意。这个解决方案不仅可以工作,而且最重要的是,它已经准备好进行分页和排序。因此,即使在内部选择返回更多“相似”的结果(相同的ID),上面的选择也只会返回每个任务一次...

更多信息:15.8. Detached queries and subqueries


0
你可以使用 left join:
Select t.* from Task t
left join UserTask ut on t.Id = ut.TaskId 
    and ut.UserId = 1 and ut.solved = 1
where ut.id is null

谢谢您的回答。不过,我需要使用nHibernate的另一种解决方案。或者说,使用nHibernate可以进行左连接吗? - Vigi Tri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接