我正在使用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)
有没有人可以举例说明如何组合查询,从而实现数据库往返并且没有应用程序端处理?
答案 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()
)