NHibernate - 联盟三个QueryOvers

Adi*_*tor 6 nhibernate queryover

您好StackOverflow用户,

我遇到了这个问题,我有三个QueryOvers,每个QueryOvers返回一个候选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))));
    }
Run Code Online (Sandbox Code Playgroud)

这将返回正确的结果,生成的查询如下所示

SELECT *
FROM   Applicants 
WHERE  IsActive = 1
   and (Id in (SELECT Id from **FirstQueryOver**)
         **or** Id in (SELECT Id from **SecondQueryOver**)
         **or** Id in (SELECT Id from **ThirdQueryOver**))
Run Code Online (Sandbox Code Playgroud)

问题是它使用'或'.因此,查询非常缓慢.

如果相反我写这个:

SELECT *
FROM   Applicants 
WHERE  IsActive = 1
   and (Id in (SELECT Id from **FirstQueryOver**
                     union SELECT Id from **SecondQueryOver**
                     union SELECT Id from **ThirdQueryOver**))
Run Code Online (Sandbox Code Playgroud)

它几乎立即完成.

您是否知道如何重构代码以获得更好的性能?

谢谢你,阿德里安.

小智 1

我搜索但没有找到任何东西,所以我做了以下黑客:

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())));
}
Run Code Online (Sandbox Code Playgroud)

这不是最好的解决方案,但应该可行。