54 messaggi dal 08 aprile 2002
Risalve a tutti!

eccomi ancora qui a sfrugugliare linq x capire
dunque... dato il solito db Northwind, creo una listview x i prodotti dove al posto del categoryID voglio la descrizione della categoria:
<td><%# Eval("Category.CategoryName")%></td>

ovviamente nel profiler mi trovo tante chiamate alla tabella <Category> quanti sono i differenti categoryID nella pagina del listview mostrata dalla select sulla tabella <Products>
allora seguendo i vari esempi sull'ottimizzazione del lazyload, il prefetch ...bla...bla... inserisco
protected void LinqDataSource1_ContextCreated(object sender, 
                                                LinqDataSourceStatusEventArgs e)
    {
        DataLoadOptions ds = new DataLoadOptions();
        ds.LoadWith<Category>(c => c.CategoryName);
        (e.Result as NorthwindDataContext).LoadOptions = ds;
    }



... ricontrollo e .... ritrovo le stesse chiamate?! ... ma com'è ma come non è... dopo un po' inserisco nella dichiarazione del linqdatasource la clausola
Select="new (ProductName,Category.CategoryName)"

e modifico il binding
<td><%# Eval("CategoryName")%></td>]

...et voilà le chiamate alla lookup spariscono e nell'unica chiamata trovo il join ...dunque tutto funziona come previsto ... ma siccome sono cornuto faccio la contrprova, ovvero commento la chiamata al metodo <LoadOptions> sul codebehind ma lascio la clausola <select>
dunque mi aspetto di ritrovare le stesse chiamate alla lookup e invece... nada!
il join è stato mantenuto e l'unica cosa che è rimasta rispetto alla versione senza prefetch è la clausola <select>...
che cosa non ho capito? la la chiamata al metodo <LoadOptions> serve o no?
chiedo lumi
Ciao,

il tuo è il più classico esempio di "N+1 Select"
Nei DataLoadOptions devi scrivere
ds.LoadWith<Product>(p => p.Category);


A presto,
m.
54 messaggi dal 08 aprile 2002
Scusami Cradle,
premesso che cosi come suggerisci funziona (nel senso che vedo il join nel profiler), avrei le sguenti obiezioni da porre:

1) in questo modo sono costretto a caricare tutta la tabella Category compreso un poco performante campo image che nella fattispecie non mi serve;

2) lo stesso risultato lo ottengo senza scrivere codice ma configurando opportunamente nel wizard del linqdatasource nello step di configurazione dei dati da selezionare;

3)come dicevo ne primo post, imponendo la calusola di <select> nel linqdatasource ottengo lo stesso risultato e, aggiungo ora, senza dover caricare il campo image; e a questo proposito volevo cheiedere se esiste una scorciatoia per dire:
Select Product.*, Category.CategoryName

visto che in realta mi sevono tutti i campi della tabella prodotto e SOLO il campo CategoryName della tabella Category

concludendo mi sembra di capire che la clausola <select> svolge direttamente nel linqdatasource il compito che,lato codice, svolge <LoadWith> ed in + posso limitare i campi da selezionare il tutto nello stesso codice inline... sbaglio?
Ciao,

il tuo problema è che Product.Category è per default lazy loaded. Il che vuol dire che viene caricato *solo* il product, poi nel momento in cui provi ad accedere alla proprietà Category scatta in maniera trasparente il fetch di quest'ultima. Nel tuo caso hai una lista di product e il fetch scatta nel momento in cui il databinding della griglia esegue
<%# Eval("Category.CategoryName")%>


Con il LoadWith stai dicendo a L2S di evitare il comportamento di default e risolvere subito, tramite una join, l'associazione Product -> Category. Ovviemtne la category viene caricata per intero, visto che potenzialmente tu potresti esplorarne ogni proprietà. Il problema del poco performante campo Image dovresti riuscere a risolverlo impostando il lazy load a livello di colonna, tramite la proprietà Delay Loaded sul designer.

Nel caso in cui usi la clausola Select, invece, stai creando un anonymous type che include proprietà di Product e Category; L2S se ne accorge e imposta correttamente la join, effettuando poi il fetch solo delle colonne che effettivamente utilizzi. Product.* non esiste, ma puoi sempre creare un tipo come
Select new {Product=product, CategoryName=category.CategoryName}


Ciao,
m.
Modificato da Cradle il 09 marzo 2009 14.44 -

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.
Community
Ultimi messaggi
UTENTI ONLINE
In primo piano

I più letti di oggi

Media
In evidenza
MISC