2013-02-14 57 views
7

所以我花了最近幾個小時尋找答案,我似乎無法找到任何有意義的東西。通過複雜的非相關實體加入nhibernate查詢

public class Game 
{ 
    public virtual Guid ID { get; set; } 
    public virtual ResultStructure Structure { get; set; } 
    public virtual List<Result> Results { get; set; } 
} 

public class Result 
{ 
    public virtual Player Player { get; set; } 
    public virtual int Position { get; set; } 
} 

public class ResultStructure 
{ 
    public virtual Guid ID { get; set; } 
    public virtual List<ResultOutcomes> Outcomes { get; set;} 
} 

public class ResultOutcomes 
{ 
    public virtual int Position { get; set; } 
    public virtual int Points { get; set; } 
} 

public class PlayerSummary 
{ 
    public virtual Player Player { get; set; } 
    public virtual int Points { get; set; } 
} 

我想要做的就是讓球員和他們已經跨越不同的遊戲衆多賺取的點的列表(上面有game多個實體包含的遊戲列表)。因此,查詢的最終結果將是List<PlayerSummary>我要找會是這個樣子的SQL:

SELECT p.*, Sum(rs.points) FROM result r 
    JOIN player p on r.playerid = p.id 
    JOIN game g on r.gameid = g.id 
    JOIN resultstructure rs on g.resultstructureid = rs.id 
    JOIN resultoutcomes ro on rs.id = ro.resultstructureid AND ro.position = r.position 

注意,我也需要做一些查詢/總結反對這就是爲什麼它的結構實體包括在內。我試圖用NHibernate做到這一點,使用TypeSafe的東西,我的計劃是爲應用程序是數據庫不可知的,所以我不能使用直接SQL(目前它使用Postgres,但我可能會移動到SQL服務器在某一點)。

我不特別想使用「HQL」的東西,你使用這些魔術字符串,所以我試圖使用Linq或QueryOver/Query。

任何人都可以指向正確的方向嗎?

+0

這是您應該使用HQL的**確切**情況。 「魔術串」並不意味着你的想法。 – 2013-02-14 15:18:23

+0

我真的想要類型安全的東西,我的確瞭解HQL ish,並且我意識到它可能會做我所需要的,但我想保留所有內容,並且我在大多數部分都使用Query。 – Martin 2013-02-14 15:26:41

+0

@DiegoMijelshon我已經添加了我的解決方案,可以詳細說明爲什麼我應該使用HQL而不是我提出的解決方案? – Martin 2013-02-14 18:50:37

回答

6

看來,以上是可能的在我的情況,因爲有一種關係,它只是不直接。可以使用JoinAlias

基本區別在於,使用JoinAlias,可以將多個表連接到同一個基表,其中與JoinQueryOver一樣,它僅通過將每個表連接到上一個表的表進行線性轉換。

所以查詢看起來像這樣。

Result resultAlias = null; 
ResultOutcome outcomeAlias = null; 
ResultStructure structureAlias = null; 

var results = Session.QueryOver(() => resultAlias) // Assigns resultAlias so it can be used further in the query. 
    .Inner.JoinQueryOver(x => x.Game) // returns a QueryOver Game so you can do a where on the game object, or join further up the chain. 
    .Inner.JoinAlias(x => x.ResultStructure,() => structureAlias) // joins on the Structure table but returns the QueryOver for the Game, not the structure. 
    .Inner.JoinAlias(() => structureAlias.Outcomes,() => outcomeAlias) // same again for the outcomes 
    .Where(() => resultAlias.Position == outcomeAlias.Position) 
    .Select(
     Projections.Group(() => resultAlias.Player), 
     Projections.Sum(() => outcomeAlias.Points) 
    ); 

這應該給人的想法。不利之處在於對「位置」的限制不會發生在Join上,而是發生在Where子句中。我很高興聽到任何有這樣做的人的選擇,因爲這會迫使數據庫查詢計劃者停止一個特定的路線。

仍在研究轉換和排序,但這讓我有更多的瞭解。

+1

因爲它是所有內部聯接,所以應該不會考慮額外聯接標準的位置......對嗎? – dotjoe 2013-02-14 20:11:04

+0

以及它們並不都是「結果」的連接,從編碼的角度來看它確實很重要。 JoinAlias可能並不重要,因爲它會嘗試與Result而不是Game進行連接,所以無法將JoinString結果放在JoinQueryOver之前。 – Martin 2013-02-14 20:46:26