Quando lavoriamo con un database, una delle operazioni più comuni è il recupero di record che corrispondono a una lista di codici. Spesso questi campi codice non sono la chiave primaria della tabella in quanto si preferisce una chiave surrogata. Supponiamo di avere una tabella Clienti con Id (Identity), Codice e Descrizione e una tabella Ordini con CodiceCliente e DatiOrdine popolata da un sistema esterno. Se volessimo recuperare i clienti relativi agli ordini dovremmo effettuare una join tra le tabelle usando il campo CodiceCliente. Sebbene quest'operazione sia semplice in SQL, con EF Core e LINQ diventa più complessa in quanto dobbiamo eseguire a mano la join. In alternativa, possiamo utilizzare un altro approccio: creiamo una prima query che recupera i codici cliente dalla tabella ordini e successivamente li usa per una IN con la tabella Clienti. Ovviamente il tutto viene fatto con un solo comando SQL, ma creando due query LINQ che si innestano come nell'esempio che segue.
var today = DateTime.Now.Date; IQueryable<string> queryCodiciCliente = Context.Ordini .Where(c => c.DataOrdine == today) .Select(c => c.CodiceCliente) .AsQueryable(); var clienti = Context.Clienti .Where(c => queryCodiciCliente.Contains(c.CodiceCliente)) .ToListAsync();
La prima riga genera una query verso la tabella degli ordini estraendo i codici cliente da recuperare. Poiché non viene eseguita la materializzazione dei dati, EF Core non esegue nessuna query. La seconda riga recupera i clienti per i codici recuperati dalla prima query. Al momento di generare il codice SQL viene generato un solo comando che innesta la prima query nella seconda come evidenziato nel prossimo esempio.
select * from Clienti where CodiceCliente in ( select CodiceCliente from Ordini where DataOrdine = @p0)
L'utilizzo di una join è leggermente più performante dell'approcio qui suggerito. Tuttavia, questo approccio offre la possibilità di spezzettare query complesse in query più semplici e di poterle integrare tra loro semplificando notevolmente il codice LINQ a scapito delle performance. Come sempre la soluzione migliore dipende dal contesto in cui ci si trova.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Definire stili a livello di libreria in Angular
Eseguire attività pianificate con Azure Container Jobs
Ottimizzare le performance delle collection con le classi FrozenSet e FrozenDictionary
Evitare la script injection nelle GitHub Actions
Effettuare il binding di date in Blazor
Creare gruppi di client per Event Grid MQTT
Gestire la cancellazione di una richiesta in streaming da Blazor
Sfruttare lo streaming di una chiamata Http da Blazor
Registrare servizi multipli tramite chiavi in ASP.NET Core 8
Eseguire query manipolando liste di tipi semplici con Entity Framework Core
Eseguire attività basate su eventi con Azure Container Jobs
Garantire la provenienza e l'integrità degli artefatti prodotti su GitHub