4

有没有办法使用 NHibernate 使这个查询更容易?

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

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

这是我在 C# 中使用 NHibernate 编写的代码

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;
}

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

4

2 回答 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 ...但意图应该很清楚)

DetachedCritera我们可以做很多事情,我们可以加入其他引用的对象/表,过滤它们……就像标准的 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...

var 结果 = 标准。列表();

笔记。该解决方案不仅可以工作;),而且大多数情况下,它已准备好进行 分页排序。因此,即使在某些情况下,内部选择将返回更多“相似”结果(相同的 id),上层选择只会返回每个任务一次......

欲了解更多信息:15.8。分离的查询和子查询

于 2013-05-13T04:03:54.750 回答
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
于 2013-05-12T21:05:02.550 回答