2013-02-14 12 views
7

Quindi ho passato le ultime ore a cercare una risposta e non riesco a trovare nulla che abbia senso.nibernare queryover con join complessi su entità non correlate

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

Quello che sto cercando di fare è ottenere una lista dei giocatori ei punti che hanno guadagnato attraverso una moltitudine di diversi giochi (ci sono più entità di cui sopra game che contengono elenchi di giochi). Così il risultato finale della query sarebbe List<PlayerSummary> L'SQL che sto cercando sarebbe simile a questa:

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 

nota, ho anche bisogno di fare qualche interrogazione/sommando contro l'entità struttura che è per questo che è incluso.

Sto cercando di farlo con NHibernate, utilizzando il materiale di tipo Safe, e il mio piano è che l'applicazione sia indipendente dal database, quindi non posso usare l'SQL diretto (al momento sta usando Postgres, ma potrei passare a Server SQL ad un certo punto).

Non voglio particolarmente utilizzare il materiale "HQL" in cui si usano quelle stringhe magiche, quindi sto cercando di usare Linq o QueryOver/Query.

Qualcuno può indicarmi la giusta direzione?

+0

Questa è la ** situazione ** esatta in cui è necessario utilizzare HQL. "Stringhe magiche" non significa quello che pensi che significhi. –

+0

Voglio davvero il tipo di cose sicure, comprendo l'HQL ish, e ho apprezzato che probabilmente farà ciò di cui ho bisogno, ma mi piacerebbe mantenere tutto uguale, e sto usando Query nella maggior parte delle parti. – Martin

+0

@DiegoMijelshon Ho aggiunto la mia soluzione, potrei elaborare il motivo per cui dovrei usare HQL sulla soluzione che ho trovato? – Martin

risposta

6

Sembra che quanto sopra sia possibile nella mia situazione in quanto esiste una relazione, non solo diretta.

È possibile utilizzare JoinAlias.

la differenza di base è che utilizzando JoinAlias, è possibile unire più tabelle per la stessa tabella di base, dove come con JoinQueryOver richiede una progressione lineare attraverso le tabelle unendo ciascuna alla tabella precedente.

quindi la query è simile a questa.

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

Che dovrebbe dare alle persone l'idea. Lo svantaggio di questo è che la restrizione su "Posizione" non si verifica sul join, ma piuttosto nella clausola Where. Sono felice di sapere da chiunque abbia un'opzione per farlo, in quanto ciò imporrebbe la pianificazione delle query del database su un percorso specifico.

Ancora lavorando alle trasformazioni e all'ordinamento, ma mi ha dato molto di più.

+1

Dal momento che sono tutti i join interni, non dovrebbe importare dove sono posizionati i criteri di aggiunta extra ... giusto? – dotjoe

+0

e dato che non si uniscono tutti a "Risultato", è importante dal punto di vista della codifica. Forse la JoinAlias ​​non ha importanza, non è possibile mettere la JoinStructure JoinAlias ​​prima di JoinQueryOver in quanto proverebbe a unirsi contro Result invece di Game. – Martin