XXP

mai 2016

lun. mar. mer. jeu. ven. sam. dim.
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          

« LINQ to SQL : eager loading, performances et bug | Accueil | LINQ to SQL : eager loading, performances et bug »

25 juin 2008

LINQ to SQL : eager loading, performances et bug

Livre Linq in action

Contrairement à Entity Framework (en tout cas, contrairement à ce que Diego Vega annonce pour Entity Framework), LINQ to SQL possède le même comportement que NHibernate vis-à-vis du lazy loading : les requêtes SQL peuvent être déclenchées à l'insu du développpeur dès qu'une collection initialisée paresseusement est énumérée. Ce comportement peut ruiner les performances d'un système. En tout cas il fait sauter au plafond les DBA qui voient passer les requêtes SQL.

La solution apportée par NHibernate consiste pour le développeur à insérer le mot-clé "fetch" dans les requêtes HQL pour forcer le chargement en une seule requête (eager loading) d'une collection d'objets associés.

La solution apportée par LINQ to SQL consiste à préciser au contexte de données les associations à fetcher via la méthode LoadWith de DataLoadOptions.

Par exemple le code suivant, adaptation d'un exemple qui accompagne le livre LINQ In Action, va exécuter autant de requête SQL que de sujets présents dans la table Subjects. Pas bien, pas beau :

public void LazyLoadingChildren_6_25()
{
DataContext dataContext =
new DataContext(Properties.Settings.Default.liaConnectionString);
dataContext.Log = Console.Out;

Table subjects = dataContext.GetTable();
foreach (Subject l_subject in subjects)
{
ObjectDumper.Write("Subject : " + l_subject.Name);
foreach (Book l_book in l_subject.Books)
{
ObjectDumper.Write("    Book title : " + l_book.Title);
}
}
}

Précisons maintenant au contexte que toute association one-to-many (ou 1:n) des Subjects vers les Books doit être chargée en une fois :

public void LazyLoadingChildren_6_25_fetch books()
{
DataContext dataContext =
new DataContext(Properties.Settings.Default.liaConnectionString);
dataContext.Log = Console.Out;

DataLoadOptions options = new DataLoadOptions();
options.LoadWith(Subject => Subject.Books);
dataContext.LoadOptions = options;
Table subjects = dataContext.GetTable();
foreach (Subject l_subject in subjects)
{
ObjectDumper.Write("Subject : " + l_subject.Name);
foreach (Book l_book in l_subject.Books)
{
ObjectDumper.Write("    Book title : " + l_book.Title);
}
}
}

La database ne reçoit maintenant qu'une seule requête SQL. Ouf. Mais...

Fetch multiple --> bug ?

Si maintenant j'ai deux boucles imbriquées, la doc de MSDN laisse penser que le même mécanisme doit s'appliquer. Le code suivant devrait n'exécuter qu'une seule requête :

public void LazyLoadingChildren_6_25()
{
DataContext dataContext =
new DataContext(Properties.Settings.Default.liaConnectionString);
dataContext.Log = Console.Out;

DataLoadOptions options = new DataLoadOptions();
options.LoadWith(subject => subject.Books);
options.LoadWith(book => book.Reviews); dataContext.LoadOptions = options; Table subjects = dataContext.GetTable();
foreach (Subject l_subject in subjects)
{
ObjectDumper.Write("Subject : " + l_subject.Name);
foreach (Book l_book in l_subject.Books)
{
ObjectDumper.Write("    Book title : " + l_book.Title);
foreach (Review l_review in l_book.Reviews)
{
ObjectDumper.Write(" Review " + l_review.Comments);
}
} } }

Malheureusement ce n'est pas le cas, je vois passer plusieurs requêtes (toujours grâce au projet VS 2008 du livre LINQ in Action), tout se passe comme si LINQ to SQL ne savait pas traiter en eager loading de multiples associations emboitées 1:n.

C'est très embêtant, ça ressemble à un bug (voir aussi LINQ To SQL: Support for Eager Loading, Really?) mais je n'ai rien vu de formalisé chez Microsoft. En savez vous plus ?

[Mise à jour] Ce problème a été reporté à l'équipe Linq et a été clos car jugé "by design" en septembre 2007. A garder en tête pour éviter de grever les performances.

TrackBack

URL TrackBack de cette note:
https://www.typepad.com/services/trackback/6a00d8341c871f53ef00e55365987c8833

Listed below are links to weblogs that reference LINQ to SQL : eager loading, performances et bug:

Commentaires

L'utilisation des commentaires est désactivée pour cette note.