4

我正在尝试在 NHibernate 中重新创建以下查询:

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,它根据订单 ID 返回任务类型列表。基本上,我正在迭代每个任务,并且对于多次发生的每个任务(因为不同的任务类型),我需要将所有这些任务添加到返回给客户端的列表中。到目前为止,这是我对 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 正在尝试针对我的目标类型 List 返回一个 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>.In(NHibernate.Criterion.QueryOve‌​r)”的类型参数。尝试明确指定类型参数。

4

1 回答 1

5

在这种情况下,子查询语法将对我们有所帮助。首先,让我们以这种方式声明内部选择:

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>()
    ;

这将创建其余部分,包含子查询

于 2013-11-02T03:53:30.130 回答