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

标签 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"])) 在循环中,就像我在原始版本中所做的那样。

最佳答案

我觉得我已经找了 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 (无论如何,这可能是更好的做法)。

关于c# - 使用 QueryOver 将相关子查询添加到 Select 语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14506754/

相关文章:

nhibernate - Fluent NHibernate 将引用映射到不是 ID 列的列

c# - nuget-packing a csproj 与 nuspec 之间的区别

c# - Linq 嵌套列表表达式

c# - Fluent NHibernate 自动映射 : Alter DateTime to Timestamp

NHibernate 不会创建代理,除非 class...lazy=true

nhibernate - 多线程应用程序中的Fluent Nhibernate配置错误

c# - Linq to 实体查询在同一个表上使用嵌套查询

c# - 如何从 .net 应用程序中的 javascript 警报框重定向到不同的页面?

NHibernate "Errors in named queries"

c# - 流利的 : has invalid child element 'many-to-one' in namespace