2013-02-14 11 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上記複数のエンティティがあります)。私もそれは、理由はある構造のエンティティに対して、加算/いくつかの照会を行う必要があります、

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 

注:だから、クエリの最終結果は、私は次のようになります探しているSQL List<PlayerSummary>だろう含まれています。

私は、TypeSafeのものを使ってNHibernateでこれをやろうとしています。私の計画はアプリケーションにデータベースに依存しないため、直接SQLは使用できません(現在はPostgresを使用していますが、いくつかの時点でSQLサーバー)。

特に、これらの魔法の文字列を使用する場所では「HQL」を使用しないので、LinqまたはQueryOver/Queryを使用しようとしています。

誰でも正しい方向に向けることができますか?

+0

これは、あなたがHQLを使うべき厳密な状況です。 「マジックストリング」は、あなたが何を意味すると思うかを意味しません。 –

+0

本当にタイプセーフなものが欲しいです、私はHQL ishを理解しています。私はそれがおそらく必要なことをすると思っていますが、私はすべて同じものを保ちたいと思います。 – Martin

+0

@DiegoMijelshon私は自分のソリューションを追加しました。なぜ、私が思いついた解決策よりもHQLを使うべきなのかについて詳しく説明できますか? – Martin

答えて

6

私の状況では、関係があるので上記のことが可能であると思われます。それは直接的ではありません。

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

それは人々に考えを与えるはずです。欠点は、「位置」の制限が結合ではなく、Where句で発生することです。私はこれを行うオプションを持っている人から聞いてうれしく思います。これはデータベースクエリプランナーに特定のルートを強制するためです。

まだ変換と順序付けに取り組んでいますが、それはさらに多くのことをもたらします。

+1

それはすべて内部結合なので、余分な結合基準がどこに置かれていても問題ありません。 – dotjoe

+0

「Result」にすべてが参加しているわけではないので、コーディングの観点からは問題ありません。 JoinAliasは問題ではないかもしれませんが、ResultStructure JoinAliasをJoinQueryOverの前に置くことができず、Gameの代わりにResultと結合しようとします。 – Martin

関連する問題