如何使用"not "做一个NHibernate的QueryOver
本文关键字:quot 一个 NHibernate QueryOver 何使用 not | 更新日期: 2023-09-27 18:13:09
是否有一种方法可以使这个查询更容易与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;
}
查询返回正确的结果,但我认为可能有一个更简单的方法来获得相同的结果。
如果您更喜欢INNER SELECT
, nhibernate确实有适合您的解决方案。它叫做DetachedCriteria
。(试着在这里查看类似的例子)
首先我们将创建内部select:
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一样。唯一的区别是,我们应该返回投影(SELECT TaskId)作为另一个查询中的过滤器:
var criteria = session.CreateCriteria<Task>();
criteria
. Where(... // your filters applied on Task
.Add(Subqueries.PropertyIn("ID", sub)); // Task.ID in (select...
var result = criteria.List();
。这个解决方案不仅可以工作,而且大多数情况下,它已经准备好了分页和排序。因此,即使在情况下,内部选择将返回更多"相似"的结果(相同的id),上层选择将只返回每个任务一次…
查看更多信息:15.8。分离查询和子查询
您可以使用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