2009-07-15 17 views
6

Sto utilizzando NHibernate con una query SQL per popolare alcuni oggetti entità.NHibernate - AddEntity e AddJoin problem

Ho un oggetto Item, che fa riferimento a un oggetto utente (per indicare il proprietario della voce)

class Item 
{ 
public User User; 
} 

mia query SQL è (in realtà è più complicata, ed è per questo che non posso usare HQL, ma ho iniziato con questo per assicurarsi che l'AddJoin/AddEntity funzionava):

SELECT {i.*}, {u.*} 
FROM Item i INNER JOIN User u ON (i.UserId = u.Id) 
WHere i.Id = 5 

Ecco il mio codice:

var x = session.CreateSQLQuery(sql) 
    .AddEntity("i", typeof(Item)) 
    .AddJoin("u", "i.User") 
    .List(); 

Quando lo eseguo, ottengo un array bidimensionale. Ogni elemento nell'array contiene un oggetto Item (con la proprietà User inizializzata) e l'oggetto User stesso.

Cosa mi manca? Speravo di ottenere una lista di oggetti Item con la proprietà User inizializzata (che è il modo in cui ho interpretato la documentazione).

risposta

0

Cosa succede se si omette il metodo AddJoin? Non è sufficiente specificare AddEntity?

1

E 'stato un po', ma penso che ti manca questo:

.SetResultTransformer(new DistinctEntityRootTransformer()) 
+0

Grazie Ben. Ho aggiunto questo - .SetResultTransformer (new DistinctRootEntityResultTransformer()) - ma poi ottengo un elenco di utenti, anziché l'elenco di elementi desiderato. Penserei che l'Entità Root sarebbe l'Oggetto, quindi qualcos'altro deve essere sbagliato. –

+0

Questo non funziona quando c'è un altro add-in. È necessario creare il proprio DistinctRootEntityResultTransformer. Vedi sotto. – Trent

0

Se la mappatura è giusto si può semplicemente utilizzare un join prendere per ottenere tutto questo in un solo colpo in questo modo:

var x = session.CreateQuery("from Item i join fetch i.User").List<Item>(); 
+0

Grazie David, ma l'attuale SQL è molto più complicato di quello che ho incluso. Avevo bisogno di capire perché l'SQL di base non restituisce ciò che mi aspetto poiché non posso usare HQL per la soluzione finale. –

5

Ho appena perso un pomeriggio per capirlo. SetResultTransformer (CriteriaUtil.DistinctRootEntity) opera sull'ultima cosa aggiunta.

Ecco cosa ho fatto per ottenere la prima entità dalla query. Una cattura però, ho dovuto modificare il NHibernate.DistinctRootEntityResultTransformer.TransformTuple() per essere virtuale. Non è un grosso problema per noi, perché abbiamo già ramificato NHibernate per alcune aggiunte banali come questa. Se non si desidera effettuare il branching di NH, sarebbe facile eseguire il rollover del proprio IResultTransformer, assicurandosi che gli articoli siano unici.

aggiungere questo alla tua richiesta:

query.SetResultTransformer(new FirstTupleDistinctResultTransformer()); 

e questa è la nuova classe:

public class FirstTupleDistinctResultTransformer : DistinctRootEntityResultTransformer 
{ 
    public override object TransformTuple(object[] tuple, string[] aliases) 
    { 
     return tuple[0]; 
    } 
} 
1

provare questo

using NHibernate.Transform; 
    //.. 

    var x = session.CreateSQLQuery(sql)  
    .AddEntity("i", typeof(Item))  
    .AddJoin("u", "i.User") 
    .AddEntity("i", typeof(Item)) 
    .SetResultTransformer(new DistinctRootEntityResultTransformer()) 

    .List(); 
3
var x = session.CreateSQLQuery(sql)  
    .AddEntity("i", typeof(Item))  
    .AddJoin("u", "i.User") 
    .AddEntity("i", typeof(Item)).setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 

tornerà unico elemento