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

クエリは正しい結果を返しますが、同じ結果を得るにはもっと簡単な方法があると思います。

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

(私はあなたのモデルとネーミングについて確信が持てませ.

多くのこと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 結果 = 基準.List();

ノート。このソリューションは機能するだけでなく、ほとんどの場合、 ページングソートの準備ができています。そのため、内側の選択がより「類似した」結果(同じID)を返す場合でも、上部の選択は各タスクを1回だけ返します...

詳しくは: 15.8. 独立したクエリとサブクエリ

于 2013-05-13T04:03:54.750 に答える