Visualizzazione dei risultati da 1 a 10 su 10
  1. #1
    Utente di HTML.it L'avatar di Veronica80
    Registrato dal
    May 2006
    Messaggi
    2,109

    [VB.NET] Costruire una query LINQ in base a variabili esterne da usare come filtro

    Ciao a tutti!
    Finalmente ci son riuscita e son passata agli Entity Frameworks.
    Riuscita in realtà è un parolone...son proprio alle basi...

    Infatti mi son bloccata su una questione che immagino sia di semplice soluzione per i più esperti!

    In sostanza vorrei costruire una SELECT in base a variabili esterne...mi spiego meglio:


    • Ho una combobox con tutte le regioni d'Italia ma anche un item "Tutte le regioni"
    • Voglio filtrare i comuni in una datagridview in base alla regione (e sin qui ci riesco usando questo codice:

    codice:
      
    //per semplificare inserisco io a mano l'id invece che recuperarlo dalla combo
    dim idRegione as integer=3
    
    Dim lista = From comune In mioEf.dgv_comuni
                            Where comune.idReg= idRegione
                            Order By comune.nome_Com, comune.id_Com
                            Select comune
    • il problema è quando seleziono l'id della voce "TUTTE LE REGIONI" e quindi non voglio filtrare per regione ma vedere tutti i comuni
    • quando usavo i mysqlCommand avrei fatto così:


    codice:
    dim strCondizione as string=""
    if idRegione=1 then
          strCondizione=" WHERE idReg=1"
    end if
    mioCmd.commandText="SELECT * FROM COMUNI" & strCondizione
    In LINQ sto incontrando qualche problemino nn essendo stringhe...

    Help


    PS: Per chi volesse consigliarmi una condizione IF a monte del tipo:

    codice:
    if idReg=1 then
    'Eseguo il codice senza filtro
    else
    'Eseguo il codice con filtro
    end if
    dico già che non è la soluzione che cerco essendo le variabili che modificano la stringa parecchie!
    Io solitamente con comandi di tipo stringa mi costruivo vere e proprie query in base alle variabili esterne, vorrei fare lo stesso con LINQ!

    Grazie ancora
    Ultima modifica di Veronica80; 22-09-2018 a 13:40

  2. #2
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,288
    La soluzione è più semplice del previsto: quando usi una espressione LINQ, stai creando un oggetto che rappresenta i risultati che vuoi estrarre da un insieme di dati, a cui puoi applicare filtri, ordinamenti, proiezioni, ecc.

    Nel tuo esempio quindi, la variabile che hai chiamato lista è fuorviante: non contiene i risultati che ti aspetti, ma rappresenta la "query" per ottenerli, definita tramite la sintassi LINQ e i metodi di estensione che mette a disposizione per le generiche "collezioni".

    Fino a quando non esegui un ciclo For, oppure non chiami ToList(), ToArray(), First(), Last() e così via, quell'oggetto rimane semplicemente una espressione, mentre coi suddetti metodi essa viene eseguita e produce i risultati richiesti; nel caso di Entity Framework, quell'espressione viene valutata e convertita in SQL (tienilo presente perché non puoi usare operatori o metodi che non sono convertibili in SQL), lanciata sul DB e poi convertita nel risultato richiesto, ovvero l'oggetto che rappresenta l'entità.

    Detto questo, puoi costruire la tua query passo per passo aggiungendo di volta in volta nuove condizioni e clausole, e lanciarla una volta sola alla fine.

    Riprendendo il tuo esempio, puoi fare qualcosa del genere (non l'ho compilato):

    codice:
    ' Prendo tutti i comuni disponibili
    Dim query = From comune In mioEf.dgv_comuni
    
    ' Aggiungo il filtro se necessario
    If idRegione <> 0 Then
      query = From comune In query
                 Where comune.idReg= idRegione
                 Select comune
    End If
    
    ' Aggiungo eventuali altri filtri alla query
    ' ...
    
    ' Eseguo finalmente la query e ottengo i risultati
    Dim lista = query.ToList()
    Se vuoi approfondire la cosa, ti segnalo anche questo mio articolo su HTML.it che parla della Deferred Execution di LINQ.

    Prima di partire, assicurati di comprendere bene il funzionamento di LINQ: a mio avviso ha dei benefici spesso poco compresi e sfruttati male, ma è uno degli strumenti più validi a disposizione nei linguaggi .NET.

    Suggerisco anche di scaricare il tool LINQPad che ti permette di sperimentare (anche con Entity Framework) e di testare le espressioni (in C# e VB.NET); alla fine potrai copiare e incollare le espressioni nel tuo programma e vederle funzionare, senza dover apportare cambiamenti.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  3. #3
    Utente di HTML.it L'avatar di Veronica80
    Registrato dal
    May 2006
    Messaggi
    2,109
    Grazie 1000 Marco!
    Si ho appena iniziato a infilarci il naso ma ho già notato la potenza di LINQ e E. Frameworks (il metodo savechanges() che gestisce le transazioni gerarchicamente in automatico è stupendo) i quali snelliscono il codice in maniera veramente straordinaria.

    Anche io uso il metodo .toList() però in effetti non avevo contestualizzato il fatto che la mia variabile "lista" è solo un espressione e non un esecuzione!

    Ora non ho l'ambiente di sviluppo non essendo in ufficio quindi non posso testare il tutto!

    Ti faccio una domanda preventiva:

    Devo dunque trattare la variabile lista come se fosse una stringa? Compoenendola a mio piacimento cone la condizioni IF?

    Scaricherò anche LinqPad che sicuramente mi farà molto ma molto comodo!

    Per adesso grazie! Ti aggiorno appena sono al pc dell'ufficio!

  4. #4
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,288
    Quote Originariamente inviata da Veronica80 Visualizza il messaggio
    Si ho appena iniziato a infilarci il naso ma ho già notato la potenza di LINQ e E. Frameworks (il metodo savechanges() che gestisce le transazioni gerarchicamente in automatico è stupendo) i quali snelliscono il codice in maniera veramente straordinaria.
    Tieni conto che LINQ costituisce un linguaggio a parte, ovvero si tratta di un supporto per costruire espressioni che esula dall'utilizzo esclusivo con Entity Framework, ma si applica a prescindere su qualsiasi "enumerabile".

    Poi, a seconda dell'oggetto di partenza (es. DbSet di EF, oppure una lista di oggetti, ecc.) che è quello a cui viene demandata l'esecuzione dell'espressione, si hanno diverse implementazioni (LINQ To SQL su ADO.NET, LINQ To Objects per liste/array/collezioni, LINQ To XML per file XML, LINQ To Entities per EF, ...) che permettono di interpretarla fattivamente e tradurla nell'implementazione opportuna che restituisce il dato desiderato.

    Quote Originariamente inviata da Veronica80 Visualizza il messaggio
    Anche io uso il metodo .toList() però in effetti non avevo contestualizzato il fatto che la mia variabile "lista" è solo un espressione e non un esecuzione!
    E' un principio fondamentale da tenere ben presente, soprattutto per gli effetti collaterali che ne possono derivare, ma anche per i vantaggi (trovi tutto nell'articolo segnalato).

    Quote Originariamente inviata da Veronica80 Visualizza il messaggio
    Ti faccio una domanda preventiva:
    Devo dunque trattare la variabile lista come se fosse una stringa? Compoenendola a mio piacimento cone la condizioni IF?
    Diciamo "ni". Sicuramente non è una stringa, ma non va pensato come qualcosa progettato per accodarvi delle clausole.

    Il principio è che una espressione LINQ parte da una enumerazione di qualcosa e permette di filtrarla (where), ordinarla order by, estrarre qualcosa di diverso o un elemento dell'insieme originale (select), ma solo nel momento in cui viene eseguita.

    Ogni espressione LINQ quindi è anche automaticamente una nuova "enumerazione" sulla quale è possibile costruire un'altra espressione, che potrebbe un altro filtro ancora, proiettare qualcosa di diverso e così via.

    Se una espressione LINQ viene usata come origine per basarvi sopra un'altra espressione, poi un'altra e un'altra ancora e così via, alla fine si ottiene una catena di elaborazioni che produrranno alla fine il risultato desiderato, con il vantaggio che l'effettiva esecuzione viene fatta una volta sola, alla fine, quando si chiama una delle funzioni di aggregazione (es. Sum, Max, ...) oppure una funzione che estrae una lista o un array dei valori (es. ToList, ToArray, ToDictionary, ...) oppure un solo elemento, come il primo (First), il primo o un valore di default (FirstOrDefault), l'ultimo (Last) e così via, oppure banalmente quando si inizia un ciclo sull'espressione.

    Se il motore che riceve l'espressione in carico è abbastanza intelligente (e quello di EF generalmente lo è), l'espressione viene combinata e semplificata per essere eseguita nel modo più veloce possibile.

    Quote Originariamente inviata da Veronica80 Visualizza il messaggio
    Scaricherò anche LinqPad che sicuramente mi farà molto ma molto comodo!
    Oltre ad essere comodo (a volte lo uso come sostituto di SQL Server Management Studio), ha proprio tutto quello che serve per analizzare le espressioni e vedere come LINQ si comporta, oltre a includere degli esempi e dei tutorial che fanno capire le potenzialità e i principi di funzionamento.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  5. #5
    Utente di HTML.it L'avatar di Veronica80
    Registrato dal
    May 2006
    Messaggi
    2,109
    Grazie Marco la spiegazione è stata abbastanza chiara!
    Però Ho capito tutto il principio ma non il modo in cui realizzardo...
    La sintassi per "comporre" la stringa qual'è?

  6. #6
    Utente di HTML.it
    Registrato dal
    Apr 2011
    residenza
    Arezzo
    Messaggi
    194
    Ti consiglio di iniziare fin da subito a studiarti le query LINQ con le lemda expression, sono estremamente versatili, più veloci ed intuitive.
    In VB la sintassi è un po' più articolata rispetto al C# dove è veramente molto semplice, comunque una volta che ci ha preso la mano ne vedi la differenza.

    Altro piccolo consiglio, se posso, fatti una serie di service con i metodi più utilizzati nella procedura e richiama sempre quelli, in modo che il codice lo centralizzi, li dividi per macro aree tipo questa dei comuni potrebbe stare in una zona relativa alle anagrafiche e quindi con tutto quello che serve per lavorarci.

    Tornando all'esempio sopra una cosa del genere potresti farla ad esempio così

    codice:
    public function GetComuni(optional byval regioneID as integer? = null) as List(Of Comuni)
    
      Dim result = _dbContext.set(Comuni).ToList()
    
      if regioneID IsNot Nothing AndAlso regioneID > 0 Then
        result = result.Where(Function(r) r.regioneID == regioneID).ToList()
      End If
    
      return result
    End Function
    ps.: io al 95% lavoro in C#, quindi se ho scritto qualche castroneria a livello di sintassi perdonami, ma concettualmente questo è quello che intendevo
    Riccardo Sadocchi
    Microsoft MCP C#

  7. #7
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,288
    Quote Originariamente inviata da rikyeko Visualizza il messaggio
    Ti consiglio di iniziare fin da subito a studiarti le query LINQ con le lemda expression, sono estremamente versatili, più veloci ed intuitive.
    La velocità di esecuzione delle query è indipendente dalla sintassi, in quanto il codice compilato (IL) è lo stesso a prescindere dal tipo di sintassi utilizzata, che sia basato su metodi lambda o con le parole chiave.

    Anche io preferisco usare funzioni lambda, ma la sintassi è un aspetto del tutto preferenziale (che io considero un'altra buona qualità di LINQ).

    Quote Originariamente inviata da rikyeko Visualizza il messaggio
    Altro piccolo consiglio, se posso, fatti una serie di service con i metodi più utilizzati nella procedura e richiama sempre quelli, in modo che il codice lo centralizzi, li dividi per macro aree tipo questa dei comuni potrebbe stare in una zona relativa alle anagrafiche e quindi con tutto quello che serve per lavorarci.
    Rilancio a pieno questo consiglio e lo estenderei con il suggerimento di lavorare il più possibile con IEnumerable<>: c'è il vantaggio di poter creare metodi che applicano espressioni senza però eseguire il risultato, che può essere ottenuto il più tardi possibile, combinando così diverse logiche senza dover necessariamente creare un metodo per ogni tipo di interrogazione.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  8. #8
    Utente di HTML.it
    Registrato dal
    Apr 2011
    residenza
    Arezzo
    Messaggi
    194
    Quote Originariamente inviata da alka Visualizza il messaggio
    La velocità di esecuzione delle query è indipendente dalla sintassi, in quanto il codice compilato (IL) è lo stesso a prescindere dal tipo di sintassi utilizzata, che sia basato su metodi lambda o con le parole chiave.

    Anche io preferisco usare funzioni lambda, ma la sintassi è un aspetto del tutto preferenziale (che io considero un'altra buona qualità di LINQ).
    Certo, probabilmente mi sono spiegato male, intendevo la velocità nella scrittura in fase di sviluppo, anche se comunque ci sono delle differenze in fase di ordine di esecuzione rispetto alla sintassi estesa
    Riccardo Sadocchi
    Microsoft MCP C#

  9. #9
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,288
    Quote Originariamente inviata da rikyeko Visualizza il messaggio
    anche se comunque ci sono delle differenze in fase di ordine di esecuzione rispetto alla sintassi estesa
    No, la differenza è solo sintattica, ma le istruzioni sono eseguite nello stesso medesimo ordine.

    Se usi LINQPad, prova ad esempio a scrivere questi due esempi di codice:
    1)
    codice:
    from word in "The quick brown fox jumps over the lazy dog".Split()
    orderby word.Length
    select word
    2)
    codice:
    "The quick brown fox jumps over the lazy dog"
    .Split()
    .OrderBy(w => w.Length)
    Se guardi la scheda del codice compilato generato (IL) vedrai che le implementazioni sono identiche.

    Questo vuol dire che, lambda o no, per la sintassi si può scegliere quello che si vuole ma il risultato finale è lo stesso, ovviamente se l'espressione che si scrive - al netto della sintassi - è la stessa, come nel caso sopra.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  10. #10
    Utente di HTML.it
    Registrato dal
    Apr 2011
    residenza
    Arezzo
    Messaggi
    194
    Ho capito, sinceramente non avevo mai fatto questo tipo di controllo, avevo letto un po' di tempo fa questa cosa e basta.
    Ottimo! thx
    Riccardo Sadocchi
    Microsoft MCP C#

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.