2012-10-03 27 views
6

嗨StackOverflow的用戶,NHibernate的 - 聯盟3個QueryOvers

我就遇到了這個問題 我有三個QueryOvers和他們每個人的返回候選IDS,我再使用帶來的候選人名單。 爲此我寫了下面的代碼。

 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**) 
     **or** Id in (SELECT Id from **SecondQueryOver**) 
     **or** Id in (SELECT Id from **ThirdQueryOver**)) 

的問題是,它使用「或」。因爲這個查詢很痛苦地慢。

相反,如果我這樣寫:

SELECT * 
FROM Applicants 
WHERE IsActive = 1 
    and (Id in (SELECT Id from **FirstQueryOver** 
        union SELECT Id from **SecondQueryOver** 
        union SELECT Id from **ThirdQueryOver**)) 

它完成幾乎瞬間。

你有什麼想法我應該如何重構代碼以獲得更好的性能?

謝謝, 阿德里安。

+0

正在做一個內存聯盟的一個選項? –

+0

@Andrew Whitaker我最終這樣做了,但我不太喜歡它,因爲有多個查詢返回的記錄,所以我必須手動刪除重複項。 –

回答

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()))); 
} 

這是不是最好的解決辦法,但應該工作。

0

我不能說爲什麼或vs工會有這樣的差異。 sql分析器,查詢分析器和估計的執行計劃應該讓你更深入地瞭解sql在運行你的查詢方面的作用,我猜它在第一種情況下沒有使用正確的索引。不過,我會嘗試將您的查詢重寫爲:

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

然後看看您有什麼樣的表現。

+0

嗨同行,感謝您的幫助。 我將檢查我的列上的索引。 但是,如果您能夠提供重構c#代碼的提示,我將非常感激。 –