Tutti conosciamo i Dire Straits, vero? Bene.
La miglior formazione dei Dire Straits, a mio avviso, è stata quella composta da:
- Mark Knopfler (voce e chitarra solista)
- John Illsley (basso)
- Hal Lindes (chitarra ritmica)
- Alan Clark (tastiere)
- Terry Williams (batteria)
Se provassimo a mappare il tutto in un modello ad oggetti, potremmo scrivere:
public class Band
{
public int BandId { get; set; }
public IList<Player> Members { get; set; }
}
public class Player
{
public int PlayerId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Band Band { get; set; }
}
E ora che abbiamo Linq2NHibernate possiamo scrivere una cosa del tipo:
using (ISession session = SessionHelper.OpenSession())
{
Band myBand = session.Linq<Band>().Expand("Members")
.Where<Band>(bnd => bnd.BandId == 1)
.FirstOrDefault<Band>();
Console.WriteLine("Nome band: {0}, numero di componenti: {1}",
myBand.Name,
myBand.Members.Count);
}
L’output però non è quello che ci aspettiamo:
Nome band: Dire Straits, numero di componenti: 1
La causa è nel codice SQL generato da Linq2NHibernate, che, da Profiler, risulta essere questo:
exec sp_executesql N'SELECT top 1 this_.BandId as BandId4_1_, this_.Name as Name4_1_,
members2_.BandId as BandId3_, members2_.PlayerId as PlayerId3_,
members2_.PlayerId as PlayerId2_0_, members2_.FirstName as FirstName2_0_,
members2_.LastName as LastName2_0_, members2_.BandId as BandId2_0_
FROM dbo.Band this_
left outer join dbo.Player members2_ on this_.BandId=members2_.BandId
WHERE this_.BandId = @p0',N'@p0 int',@p0=1
In pratica, la chiamata a FirstOrDefault() aggiunge quel TOP 1 all’SQL generato, che fa sì che venga ritornata solo una riga ritornata dal DB, falsando il conteggio.
I modi per risolvere la questione sono due:
- Tornare ad usare la Criteria API :).
- Sostituire
FirstOrDefault<Band>()conToList<Band>()[0].
In questo modo, la clausola TOP sparisce e i Dire Straits tornano ad essere cinque:
Nome band: Dire Straits, numero di componenti: 5