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

    [VB.NET] Filtrare in tempo reale DataGridView interfacciata a Entity Framework

    Ciao a tutti! Chi ha visto i miei recenti post saprà che sto sbattendo la testa con dataset/entity ecc ecc

    In realtà io ho sempre usato la libreria MySQLData per accedere ai dati dei DB mySQL che uso negli applicativi che sviluppo! Facendo un po tutto il lavoro "a mano" senza binding ecc.

    Dacchè non ne ho cavato piede cambiando metodo di connessione (dataset/entity ecc appunto) espongo direttamente il mio problema a monte.

    Io ho delle datagridview che popolo con una mole importante di dati (sino a 20.000 righe) e che vorrei filtrare in tempo reale scrivendo in una textbox agganciando l'evento textChanged della textbox stessa.

    Ho ottenuto un risultato più che soddisfacente usando un bindingsource che filtravo man mano che si scrive la parola che funge da filtro nella textbox. Velocissimo ed efficente.
    Purtroppo però questo metodo presupponeva l'utilizzo dei dataset che si sono rivelati estremamente carenti nella gestione del DB (non gestiscono i valori Null, mi creavano problemi in update di più tabelle con transazioni ecc).

    Alchè son passata agli entity frameworks (che devo dire mi stanno piacendo molto) ma senza l'uso dei bindingsourc (con gli EF ottengo una lista che poi va fare da datasource alla datagridview) il popolamento delle grid è davvero molto molto lento (quando filtro in tempo reale scrivendo nelle textbox di cui sopra)...

    Alchè tralasciando il discorso connessione, dataset ecc vi chiedo:

    Qual'è il metodo migliore per ottenere il risultato di un filtro in una datagridview senza che ci vogliano secondi e secondi per terminare l'operazione?

    Non so se mi son spiegata chiaramente su ciò che voglio ottenere! Nel caso chiedete pure!
    Non so più che pesci pigliare
    Grazie a tutti!

  2. #2
    Utente di HTML.it L'avatar di Veronica80
    Registrato dal
    May 2006
    Messaggi
    2,110
    Veramente non è mai capitato a nessuno di dover fare una cosa simile?!?

  3. #3
    Utente di HTML.it
    Registrato dal
    Apr 2011
    residenza
    Arezzo
    Messaggi
    194
    Visto che sei passata a EF e LINQ, se fai il binding su un oggetto che contiene tutta la lista che recuperi all'avvio, puoi filtrare quello con le LINQ appunto, bindando poi il DGW all'oggetto nuovo filtrato
    Riccardo Sadocchi
    Microsoft MCP C#

  4. #4
    Utente di HTML.it L'avatar di Veronica80
    Registrato dal
    May 2006
    Messaggi
    2,110
    Si infatti l'idea era quella ma vedo che rallenta molto!
    Rispetto all'uso dei dataset+bindingsource mi "scatta" quando scrivo...

  5. #5
    Quote Originariamente inviata da Veronica80 Visualizza il messaggio
    Si infatti l'idea era quella ma vedo che rallenta molto!
    Rispetto all'uso dei dataset+bindingsource mi "scatta" quando scrivo...
    La butto li...
    Ma non è che EF ti fa l' eagerly loading, ovvero ti carica anche tutte le eventuali entità correlare?

  6. #6
    Utente di HTML.it L'avatar di Veronica80
    Registrato dal
    May 2006
    Messaggi
    2,110
    Non ho capito la domanda non sono ancora così ferrata sugli EF :'D

  7. #7
    Quote Originariamente inviata da Veronica80 Visualizza il messaggio
    Non ho capito la domanda non sono ancora così ferrata sugli EF :'D
    Cerca con san Google eager and lazy loading. Anche se non fosse questo il motivo imparerai qcs di nuovo.
    ... Potresti anche analizzare le query inviate da ef a sql server

  8. #8
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,296
    Quote Originariamente inviata da Veronica80 Visualizza il messaggio
    Si infatti l'idea era quella ma vedo che rallenta molto!
    Rispetto all'uso dei dataset+bindingsource mi "scatta" quando scrivo...
    Io proverei a riportare un pochino di codice, giusto per capire come viene effettuata la gestione del filtro.

    C'è ad esempio la probabilità che tu vada a eseguire la query ogni volta che il filtro cambia, però senza vedere come hai usato effettivamente il framework è difficile fare delle ipotesi.

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

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

  9. #9
    Utente di HTML.it L'avatar di Veronica80
    Registrato dal
    May 2006
    Messaggi
    2,110
    Allora io sto usando questo metodo
    codice:
        Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
            Using mioEf As New efTotDb
                Dim qry = From o In mioEf.dgv_ospiti
                          Where o.cognome_Osp.StartsWith(TextBox1.Text)
                          Select o
                dgvOsp.Rows.Clear()
                Dim lista As List(Of dgv_ospiti) = qry.ToList()
                For Each ospite As dgv_ospiti In lista
                     dim imgSex as bitmap=my.resources.maschio
                      if ospite.sesso_Osp=true then
                               imgSex=my.resources.femmina
                      end if
                    dgvOsp.Rows.Add(ospite.id_Osp, ospite.sesso_Osp, imgSex,  ospite.cognome_Osp, ospite.nome_Osp, ospite.cf_Osp,  ospite.indirizzo_Osp, ospite.com_Res, ospite.prov_Res,  ospite.dataNascita_Osp, ospite.com_Nas, ospite.com_Res)
                Next
            End Using
        End Sub


    Non sto usando: dgvOsp.dataSource=qry.toList() perchè ho alcune colonne "unbounded" che visualizzano immagini a seconda del valore di campi del db (tipo sesso_Osp è una colonna invisibile che uso per ottenere il valore e poi mettere l'immagine del sesso appropiata nella colonna apposita)

    Un esempio del problema è che se cancello il testo dalla textbox (quindi mi ricarica tutti i record) si ferma per tipo 3 sec (son molti records...) ed il mio pc è un bel pc eh!
    Quando invece usavo il bindingsource e "filter" (coi dataset) era perfetto
    Ultima modifica di Veronica80; 10-10-2018 a 12:40

  10. #10
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,296
    Quote Originariamente inviata da Veronica80 Visualizza il messaggio
    Allora io sto usando questo metodo [...]
    Come sospettavo, stai ripetendo l'interrogazione al DB ogni volta che il valore della casella di testo cambia, quindi è normale notarlo (anche se l'operazione può essere relativamente veloce).

    Quello che sarebbe invece più opportuno è eseguirla una volta sola, e poi filtrare magari sui risultati già acquisiti, sempre se non sono troppi.

    Andando per gradi, quando costruisci una espressione LINQ che si basa sul DbContext di Entity Framework, nel nostro caso ipotizzo sia la variabile efTotDb, di fatto stai costruendo una struttura che rappresenta una interrogazione che verrà affidata a EF, ovvero convertita successivamente in SQL ed eseguita, memorizzando poi i valori dei record recuperati all'interno di oggetti. Questo avviene solo chiamando un metodo che lancia l'esecuzione dell'espressione, come ad esempio ToList.

    La prima parte del tuo codice fa proprio questo:
    codice:
                Dim qry = From o In mioEf.dgv_ospiti
                          Where o.cognome_Osp.StartsWith(TextBox1.Text)
                          Select o
                Dim lista As List(Of dgv_ospiti) = qry.ToList()
    Io invece toglierei il filtro dall'espressione sopra, in modo che vengano recuperati tutti i dati, o alla peggio applicando un altro filtro che limiti il resultset ma non in base al valore inserito nella casella.

    Questo caricamento lo farei una volta sola all'apertura della finestra, o comunque inizialmente e a seguito di un comando di refresh forzato. Poi andrei ad applicare il filtro su quei risultati, magari usando sempre LINQ.

    Per spiegarmi, da qualche parte (es. Form_Load) metterei il caricamento fatto circa così:
    codice:
    Dim listaOspiti = mioEf.dgv_ospiti.ToList()
    In questo modo, recuperiamo tutte le entità da Entity Framework.

    Quando il testo della casella cambia, lo gestirei così:
    codice:
        Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
            Dim lista As List(Of dgv_ospiti)
            lista = From o In listaOspiti
                    Where o.cognome_Osp.StartsWith(TextBox1.Text)
                    Select o
    		dgvOsp.Rows.Clear()
    		For Each ospite As dgv_ospiti In lista
    			 dim imgSex as bitmap=my.resources.maschio
    			  if ospite.sesso_Osp=true then
    					   imgSex=my.resources.femmina
    			  end if
    			dgvOsp.Rows.Add(ospite.id_Osp, ospite.sesso_Osp, imgSex,  ospite.cognome_Osp, ospite.nome_Osp, ospite.cf_Osp,  ospite.indirizzo_Osp, ospite.com_Res, ospite.prov_Res,  ospite.dataNascita_Osp, ospite.com_Nas, ospite.com_Res)
    		Next
        End Sub
    In breve, applicherei il filtro sempre e solo a oggetti caricati precedentemente in memoria e veloci da filtrare, senza eseguire di nuovo la query.

    La sintassi LINQ è la stessa, poiché non dipende dall'ambito, ma in questo caso viene usata per costruire una espressione basata su oggetti e non una query SQL per interrogare dei dati.

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

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

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.