Innestare una query nel metodo Contains di Entity Framework Core

di Stefano Mostarda, in LINQ, Entity Framework,

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

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi