使用QueryOver将相关子查询添加到Select语句

时间:2013-01-24 17:04:23

标签: c# nhibernate fluent-nhibernate

我正在尝试将SQL语句转换为使用QueryOver(希望预先获取响应中的实体部分),但我无法弄清楚如何将相关子查询添加到Select语句(所有我发现的例子只在Where子句中使用子查询显示。

这是我想要转换的查询:

var pendingFeedbackStatus = Session.QueryOver<FeedbackStatus>().Where(fs => fs.Name == "pending");
var projectWhereClause = project != null ? "AND f1.project_id = " + project.Id : "";

var query = Session.CreateSQLQuery(string.Format(@"
        SELECT
            ft.id as FEEDBACK_TYPE_ID,
            (SELECT COUNT(*) FROM FEEDBACK f1 WHERE ft.id = f1.feedback_type_id AND f1.archive_ind = 0 {0}) as ALL_FEEDBACK_COUNT,
            (SELECT COUNT(*) FROM FEEDBACK f1 WHERE ft.id = f1.feedback_type_id AND f1.archive_ind = 0 {0} AND feedback_status_id = {1}) as PENDING_FEEDBACK_COUNT
        FROM feedback f
        RIGHT JOIN feedback_type ft on f.feedback_type_id = ft.id WHERE ft.RESTRICTED_IND = 0
        GROUP BY ft.id, ft.sort_order
        ORDER BY ft.sort_order",
        projectWhereClause,
        pendingFeedbackStatus.Id
    ))
    .SetResultTransformer(Transformers.AliasToEntityMap);

var results =  query.List<IDictionary>();
return results.Select(r =>
    new FeedbackTypeSummary
    {
        Type = Get(Convert.ToInt32(r["FEEDBACK_TYPE_ID"])),
        AllFeedbackCount = Convert.ToInt32(r["ALL_FEEDBACK_COUNT"]),
        PendingFeedbackCount = Convert.ToInt32(r["PENDING_FEEDBACK_COUNT"])
    }).ToList();

这是我到目前为止(除了相关的子查询以及添加到子查询的一些额外过滤之外的大部分内容):

var pendingFeedbackStatus = Session.QueryOver<FeedbackStatus>().Where(fs => fs.Name == "pending");

Feedback feedbackAlias = null;
FeedbackType feedbackTypeAlias = null;

var allFeedback = QueryOver.Of<Feedback>()
    .Where(f => f.Type.Id == feedbackTypeAlias.Id)
    .Where(f => !f.IsArchived);

var pendingFeedback = QueryOver.Of<Feedback>()
    .Where(f => f.Type.Id == feedbackTypeAlias.Id)
    .Where(f => !f.IsArchived)
    .Where(f => f.Status.Id == pendingFeedbackStatus.Id);

var foo = Session.QueryOver<Feedback>(() => feedbackAlias)
    .Right.JoinAlias(f => f.Type, () => feedbackTypeAlias, ft => !ft.IsRestricted)
    .SelectList(list => list
        // TODO: Add correlated subqueries here?
        .SelectGroup(() => feedbackTypeAlias.Id)
        .SelectGroup(() => feedbackTypeAlias.SortOrder)
     )
    .OrderBy(() => feedbackTypeAlias.SortOrder).Asc;

var test = foo.List<object[]>();

我还想找到一种方法从语句中返回一个完整的FeedbackType实体,而不是返回feedbackTypeAlias.Id,然后像我一样在循环中执行Type = Get(Convert.ToInt32(r["FEEDBACK_TYPE_ID"]))原来。

1 个答案:

答案 0 :(得分:2)

我觉得我这样做了10次,但是我忽略了提供所需相关子查询的.SelectSubQuery()方法。这个答案让我失望 - https://stackoverflow.com/a/8143684/191902

以下是完整的QueryOvery版本:

var pendingFeedbackStatus = Session.QueryOver<FeedbackStatus>().Where(fs => fs.Name == "pending").SingleOrDefault();

Domain.Feedback.Feedback feedbackAlias = null;
FeedbackType feedbackTypeAlias = null;
var allFeedback = QueryOver.Of<Domain.Feedback.Feedback>()
    .Where(f => f.Type.Id == feedbackTypeAlias.Id)
    .Where(f => !f.IsArchived);

var pendingFeedback = QueryOver.Of<Domain.Feedback.Feedback>()
    .Where(f => f.Type.Id == feedbackTypeAlias.Id)
    .Where(f => !f.IsArchived)
    .Where(f => f.Status.Id == pendingFeedbackStatus.Id);

if (project != null)
{
    allFeedback.Where(f => f.Project.Id == project.Id);
    pendingFeedback.Where(f => f.Project.Id == project.Id);
}

FeedbackTypeSummary result = null;
var query = Session.QueryOver<Domain.Feedback.Feedback>(() => feedbackAlias)
    .Right.JoinAlias(f => f.Type, () => feedbackTypeAlias, ft => !ft.IsRestricted)
    .SelectList(list => list
        .SelectSubQuery(allFeedback.ToRowCountQuery()).WithAlias(() => result.AllFeedbackCount)
        .SelectSubQuery(pendingFeedback.ToRowCountQuery()).WithAlias(() => result.PendingFeedbackCount)
        .SelectGroup(() => feedbackTypeAlias.Id).WithAlias(() => result.TypeId)
        .SelectGroup(() => feedbackTypeAlias.Name).WithAlias(() => result.TypeName)
        .SelectGroup(() => feedbackTypeAlias.NamePlural).WithAlias(() => result.TypeNamePlural)
        .SelectGroup(() => feedbackTypeAlias.SortOrder)
    )
    .OrderBy(() => feedbackTypeAlias.SortOrder).Asc
    .TransformUsing(Transformers.AliasToBean<FeedbackTypeSummary>());

var results = query.List<FeedbackTypeSummary>();
return results;

我还能够从单个查询填充我的FeedbackTypeSummary DTO,虽然我找不到一种方法来为一个实体添加别名,最终从FeedbackType中提取了一些所需的属性FeedackTypeSummary(这可能是更好的事情)。