NHibernate-联合三个查询器

NHibernate-联合三个查询器,nhibernate,queryover,Nhibernate,Queryover,嗨,StackOverflow用户 我遇到了这个问题 我有三个查询器,每个查询器都返回一个候选ID列表,然后我使用这些ID来查找这些候选ID。 为此,我编写了以下代码 private IQueryOver<CandidateEntity, CandidateEntity> UnionPublicWithPrivateCandidates( IQueryOver<CandidateEntity, CandidateEntity> public

嗨,StackOverflow用户

我遇到了这个问题 我有三个查询器,每个查询器都返回一个候选ID列表,然后我使用这些ID来查找这些候选ID。 为此,我编写了以下代码

        private IQueryOver<CandidateEntity, CandidateEntity> UnionPublicWithPrivateCandidates(
        IQueryOver<CandidateEntity, CandidateEntity> publicCandidates, 
        IQueryOver<CandidateEntity, CandidateEntity> privateCandidate, 
        IQueryOver<CandidateEntity, CandidateEntity> candidatesByUserRole)
    {
        return ActiveCandidatesQueryOver.Where(Restrictions.Disjunction()
                                        .Add(Subqueries
                                            .WhereProperty<CandidateEntity>(c => c.Id)
                                            .In((QueryOver<CandidateEntity>)publicCandidates.Select(c => c.Id)))
                                        .Add(Subqueries
                                            .WhereProperty<CandidateEntity>(c => c.Id)
                                            .In((QueryOver<CandidateEntity>)privateCandidate.Select(c => c.Id)))
                                        .Add(Subqueries
                                            .WhereProperty<CandidateEntity>(c => c.Id)
                                            .In((QueryOver<CandidateEntity>)candidatesByUserRole.Select(c => c.Id))));
    }
问题是它使用了“或”。因此,查询速度非常慢

如果我写的是:

SELECT *
FROM   Applicants 
WHERE  IsActive = 1
   and (Id in (SELECT Id from **FirstQueryOver**
                     union SELECT Id from **SecondQueryOver**
                     union SELECT Id from **ThirdQueryOver**))
它几乎立刻就结束了

你知道我应该如何重构代码以获得更好的性能吗

谢谢,,
阿德里安。

我说不出为什么or和联盟之间有如此大的差异。sql探查器、查询分析器和估计执行计划应该让您更深入地了解sql在运行查询时所做的工作,我想在第一种情况下,它没有使用正确的索引。但是,我会尝试将您的查询改写为:

SELECT *
  FROM   Applicants  
  WHERE  IsActive = 1
    and (this_.Id in (SELECT this_0_.Id from **FirstQueryOver** 
                                          or **SecondQueryOver** 
                                          or **ThirdQueryOver**))

然后看看你有什么表现。

我搜索了一下,但没有找到任何东西,所以我进行了以下黑客攻击:

private IQueryOver<CandidateEntity, CandidateEntity> UnionPublicWithPrivateCandidates(
                  IQueryOver<CandidateEntity, CandidateEntity> publicCandidates,
                  IQueryOver<CandidateEntity, CandidateEntity> privateCandidate,
                  IQueryOver<CandidateEntity, CandidateEntity> candidatesByUserRole)
{
    var excludedQueryCandidates = QueryOver
        .WithSubquery.WhereNotExists(((QueryOver<CandidateEntity>)publicCandidates.Select(x => x.Id)))
        .WithSubquery.WhereNotExists((QueryOver<CandidateEntity>)privateCandidate.Select(x => x.Id))
        .WithSubquery.WhereNotExists((QueryOver<CandidateEntity>)candidatesByUserRole.Select(x => x.Id));

    return QueryOver.WithSubquery.WhereNotExists((QueryOver<CandidateEntity>) excludedQueryCandidates.Select(Projections.Distinct(Projections.Id())));
}
private IQueryOver UnionPublicWith private候选人(
在公众候选人中,
IQueryOver Private候选人,
IQueryOver候选用户(按用户角色)
{
var excludedQueryCandidates=QueryOver
.WithSubquery.WhereNotExists(((QueryOver)publicpardidates.Select(x=>x.Id)))
.WithSubquery.WhereNotExists((QueryOver)privateCandidate.Select(x=>x.Id))
.WithSubquery.WhereNotExists((QueryOver)candidatesByUserRole.Select(x=>x.Id));
返回QueryOver.WithSubquery.WhereNotExists((QueryOver)excludedQueryCandidates.Select(Projections.Distinct(Projections.Id()));
}

这不是最好的解决方案,但应该有效

嗨,同伴,谢谢你的帮助。我将检查列上的索引。不过,如果你能在重构c代码方面给我一些提示,我将不胜感激。在内存中进行联合是一种选择吗?@Andrew Whitaker我最终只是这样做了,但我并不喜欢这样做,因为有多个查询返回的记录,所以我必须手动消除重复的记录。
private IQueryOver<CandidateEntity, CandidateEntity> UnionPublicWithPrivateCandidates(
                  IQueryOver<CandidateEntity, CandidateEntity> publicCandidates,
                  IQueryOver<CandidateEntity, CandidateEntity> privateCandidate,
                  IQueryOver<CandidateEntity, CandidateEntity> candidatesByUserRole)
{
    var excludedQueryCandidates = QueryOver
        .WithSubquery.WhereNotExists(((QueryOver<CandidateEntity>)publicCandidates.Select(x => x.Id)))
        .WithSubquery.WhereNotExists((QueryOver<CandidateEntity>)privateCandidate.Select(x => x.Id))
        .WithSubquery.WhereNotExists((QueryOver<CandidateEntity>)candidatesByUserRole.Select(x => x.Id));

    return QueryOver.WithSubquery.WhereNotExists((QueryOver<CandidateEntity>) excludedQueryCandidates.Select(Projections.Distinct(Projections.Id())));
}