2013-11-01 5 views
2

Я пытаюсь воссоздать следующий запрос в NHibernate:SQL запросов для NHibernate с HAVING COUNT

SELECT DISTINCT 
     orderid , 
     tasktype 
FROM "Task" 
WHERE orderid IN (SELECT orderid 
        FROM "Task" 
        GROUP BY orderid 
        HAVING COUNT(orderid) > 1) 
ORDER BY orderid 

В NH, мне нужна QueryOver, которая возвращает список типов задач на основе идентификатора заказа. В основном, я повторяю каждую задачу, и для каждой задачи, которая возникает более одного раза (из-за другого типа задачи), мне нужно добавить все эти задачи в список, который возвращается клиенту. Это то, что я пробовал до сих пор с NH.

var taskList = new List<Task>(); 
PendingTasks = session.QueryOver<Model.Task>() 
       .WhereRestrictionOn(c => c.OrderId).IsIn(taskList) 
       .SelectList 
       (list => list 
       .SelectGroup(b => b.OrderId) 
       .Select(b => b.TaskType) 
      ) 
       .Where(Restrictions.Eq(Projections.Count<Model.Task>(x => x.OrderId), taskList.Count() > 1)) 
       .TransformUsing((Transformers.AliasToBean<TaskType>())) 
       .List<TaskType>() 

Я только что начал NH и нашел здесь несколько примеров относительно использования группировки и наличия. Свойство из модели, которую я возвращаю клиенту, здесь, где TaskType является простым перечислением.

public List<TaskType> PendingTasks { get; set; } 

Мне кажется, до сих пор, что QueryOver пытается вернуть IList, против моего целевого типа списка, однако нет .ToList(), так что я не знаю, что это будет возвращаться. Любая помощь, соответствующая запросу sql выше, полезна.

ОБНОВЛЕНИЕ: Метод Весь:

private static readonly string[] TaskTypeKeys = Enum.GetNames(typeof(TaskType)); 

var tasksByType = new List<TaskGroup>(); 
       Task taskObject = null; 
       QueryOver subQuery = QueryOver.Of<Task>() 
          .Select(
          Projections.GroupProperty(
           Projections.Property<Task>(t => t.OrderId) 
          ) 
          ) 
          .Where(Restrictions.Gt(Projections.Count<Task>(t => t.OrderId), 1)); 

       foreach (var type in TaskTypeKeys) 
       { 
        TaskType typeEnum; 
        Enum.TryParse(type, out typeEnum); 

        var tasks = session.QueryOver<Model.Task>() 
         .Where(
          task => 
          task.TaskType == typeEnum && 
          task.Completed == false && 
          task.DueDate <= DateTime.Today 
         ) 
         .OrderBy(t => t.DueDate).Asc 
         .List<Model.Task>() 
         .Select(t => new Task() 
          { 
           Id = t.Id, 
           OrderId = t.OrderId, 
           CustomerId = t.CustomerId, 
           CustomerName = t.CustomerName, 
           GroupName = t.GroupName, 
           TripDate = t.TripDate, 
           TaskType = TaskTypeTitles[t.TaskType.ToString()], 
           DueDate = t.DueDate, 
           Completed = t.Completed, 
           IsActiveTask = t.IsActiveTask, 

           PendingTasks = session.QueryOver<Task>(() => taskObject) 
                     // the WHERE clause: OrderId IN (subquery) 
            .WithSubquery 
            .WhereProperty(() => taskObject.OrderId) 
        ERROR-------> .In(subQuery) 

            // the rest of your SELECT/projections and transformation 
            .SelectList(list => list 
             .SelectGroup(b => b.OrderId) 
             .Select(b => b.TaskType) 
            ) 
            .TransformUsing((Transformers.AliasToBean<TaskType>())) 
            .List<TaskType>() 
          } 
         ).ToList(); 

        tasksByType.Add(new TaskGroup() 
         { 
          Title = TaskTypeTitles[type.ToString()], 
          Content = tasks, 
          RemainingCount = tasks.Count(), 
          OverdueCount = 
           tasks.Count(
            task => 
            task.DueDate < DateTime.Today), 
         }); 
       }; 

       return tasksByType; 

Аргументы типа для метода 'NHibernate.Criterion.Lambda.QueryOverSubqueryPropertyBuilderBase, Api.Task, Api.Task> .В (NHibernate.Criterion.QueryOve г)' не может быть выведено из использования. Попробуйте явно указать аргументы типа.

ответ

3

Синтаксис подзапроса поможет нам в этом случае. Прежде всего, давайте объявим внутренний выбрать этот путь:

QueryOver<Task> subQuery = QueryOver.Of<Task>() 
    .Select(
     Projections.GroupProperty(
      Projections.Property<Task>(t => t.OrderId) 
     ) 
    ) 
    .Where(Restrictions.Gt(Projections.Count<Task>(t => t.OrderId), 1)) 
    ; 

Это будет производить:

(SELECT this_0_.OrderId as y0_ 
    FROM [Task] this_0_ 
    GROUP BY this_0_.OrderId 
    HAVING count(this_0_.OrderId) > 1) 

Теперь мы можем использовать его в качестве подзапроса во внешнем SELECT:

Task task = null; 
var PendingTasks = 
    session.QueryOver<Task>(() => task) 
    // the WHERE clause: OrderId IN (subquery) 
    .WithSubquery 
    .WhereProperty(() => task.OrderId) 
    .In(subQuery) 

    // the rest of your SELECT/projections and transformation 
    .SelectList(list => list 
     .SelectGroup(b => b.OrderId) 
     .Select(b => b.TaskType) 
    )   
    .TransformUsing((Transformers.AliasToBean<TaskType>())) 
    .List<TaskType>() 
    ; 

И это создаст остальные, с включенным подзапросом

+0

Мне нравится разделение там. Но получить ошибку в .In (subQuery)? Аргументы типа для метода 'NHibernate.Criterion.Lambda.QueryOverSubqueryPropertyBuilderBase , Api.Task, Api.Task> .In (NHibernate.Criterion.QueryOver )' не может быть выведено от использования. Попробуйте явно указать аргументы типа. Нужно больше разделения внутри подзапроса? – jcc

+0

Отсканированный фрагмент работает для меня из коробки. Поэтому проверьте тип и пространство имен или покажите полный код с трассировкой стека, пожалуйста –

+0

Я обновил свой вопрос с помощью всего метода, это ошибка компиляции. – jcc

Смежные вопросы