加入多个查询以优化QueryOver查询

时间:2013-11-18 14:42:39

标签: c# nhibernate select eager-loading queryover

我正在使用NHibernate,在遍历我的代码时,我遇到了两个按顺序调用的函数。它们可能是1)额外的数据库往返和2)应用程序端的内存处理的学校示例。涉及的代码是:

 // 1) Getting the surveys in advance
 var surveys = DatabaseServices.Session.QueryOver<Survey>()
    .Where(x => x.AboutCompany.IsIn(companyAccounts.ToList()))

 // Actual query that can be optimized
 var unverifiedSurveys = DatabaseServices.Session.QueryOver<QuestionInSurvey>()
       .Where(x => x.Survey.IsIn(surveys.ToList()))
       .And(x => x.ApprovalStatus == status)
       .List();

 // 2) In-memory processing
 return unverifiedSurveys.Select(x => x.Survey).Distinct()
      .OrderByDescending(m => m.CreatedOn).ToList();

我可以使用1 .TransformUsing(Transformers.DistinctRootEntity)

完成read that the actual Distinct() operation with the QueryOver API

有没有人可以举例说明如何组合查询,从而实现数据库往返并且没有应用程序端处理?

2 个答案:

答案 0 :(得分:1)

这可能是这样的,需要对Survey的所有属性进行明确的投影。我想有一个更好的解决方案,但无法达到它;-)希望这无论如何都会有所帮助。

Survey surveyAlias = null;

var result = 
session.QueryOver<QuestionInSurvey>()
    .JoinAlias(x => x.Survey, () => surveyAlias)
    .WhereRestrictionOn(() => surveyAlias.AboutCompany).IsIn(companyAccounts.ToList())
    .And(x => x.ApprovalStatus == status)
    .Select(
        Projections.Distinct(
        Projections.ProjectionList()
            .Add(Projections.Property(() => surveyAlias.Id))
            .Add(Projections.Property(() => surveyAlias.AboutCompany))
            .Add(Projections.Property(() => surveyAlias.CreatedOn))
        )
    )
    .OrderBy(Projections.Property(() => surveyAlias.CreatedOn)).Desc
    .TransformUsing(Transformers.AliasToBean<Survey>())
    .List<Survey>();

答案 1 :(得分:1)

此方案中最合适的方法是使用Subselect。我们将首先创建分离查询(将作为主查询的一部分执行)

Survey survey = null;
QueryOver<Survey> surveys = QueryOver.Of<Survey>(() => survey)
    .Where(() => survey.AboutCompany.IsIn(companyAccounts.ToList()))
    .Select(Projections.Distinct(Projections.Property(() => survey.ID)));

所以,我们现在拥有的是一个声明,它将返回内部选择。现在主要查询:

QuestionInSurvey question = null;
var query = session.QueryOver<QuestionInSurvey>(() => question)
    .WithSubquery
    .WhereProperty(() => qeustion.Survey.ID) 
    .In(subQuery) // here we will fitler the results
   .And(() => question.ApprovalStatus == status)
   .List();

我们得到的是:

SELECT ...
FROM QuestionInSurvey
WHERE SurveyId IN (SELECT SurveyID FROM Survey ...)

因此,在一次访问DB的过程中,我们将收到所有数据,这些数据将在数据库端完全过滤...因此我们提供了“不同”的值集,甚至可以分页({{1} },Take()