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
Utilizzare politiche di resiliency con Azure Container App
Utilizzare Azure Cosmos DB con i vettori
Persistere la ChatHistory di Semantic Kernel in ASP.NET Core Web API per GPT
Sfruttare MQTT in cloud e in edge con Azure Event Grid
Triggerare una pipeline su un altro repository di Azure DevOps
Evitare (o ridurre) il repo-jacking sulle GitHub Actions
Utilizzare il trigger SQL con le Azure Function
Generare un hash con SHA-3 in .NET
Ottimizzare la latenza in Blazor 8 tramite InteractiveAuto render mode
Installare le Web App site extension tramite una pipeline di Azure DevOps
Sfruttare lo stream rendering per le pagine statiche di Blazor 8
Utilizzare Copilot con Azure Cosmos DB