web-dev-qa-db-fra.com

Meilleure façon de remplir DataGridView avec une grande quantité de données

J'ai un formulaire Windows qui a deux DataGridViews (DGV) qui contiendront plus de 25 000 enregistrements et 21 colonnes chacun. J'ai chargé avec succès chacune des données de la base de données à l'aide d'un DataAdapter, puis j'ai simplement essayé de remplir les DGV à l'aide de boucles for. Chaque méthode a pris à peu près le même temps. La première fois que les données sont renseignées dans les DGV, cela prend trop de temps (plus de 7 minutes), puis les temps suivants sont beaucoup plus raisonnables (~ 30 secondes). Ma question est donc la suivante: quel est le meilleur moyen de charger un DGV avec une grande quantité de données qui prendra en moyenne <= 1 min? J'aime beaucoup les fonctionnalités des DGV, mais si Push venait à être utilisé, je serais prêt à utiliser une technologie différente, même si cela impliquait de renoncer à certaines de ces fonctionnalités. 

20
Bkins

Il existe fondamentalement 3 façons d’afficher des données dans un DataGridView

  • Créez les lignes manuellement dans une boucle, comme vous le faites actuellement: comme vous l'avez remarqué, c'est très inefficace si vous avez beaucoup de données

  • Utilisez le mode virtuel du DataGridView, comme suggéré par Jonathan dans son commentaire: le DGV crée uniquement le nombre de lignes pouvant être affichées et modifie dynamiquement leur contenu lorsque l'utilisateur fait défiler. Vous devez gérer l'événement CellValueNeeded pour fournir les données requises au DGV.

  • Utiliser la liaison de données: c'est de loin le moyen le plus simple. Vous venez de remplir un DataTable avec les données de la base de données à l'aide d'un DbDataAdapter et vous affectez ce DataTable à la propriété DataSource du DGV. Le DGV peut créer automatiquement les colonnes (AutoGenerateColumns = true) ou vous pouvez les créer manuellement (vous devez définir la variable DataPropertyName de la colonne sur le nom du champ que vous souhaitez afficher). En mode lié aux données, le fichier DGV fonctionne comme en mode virtuel, à la différence qu'il se charge d'extraire les données de la source de données, de sorte que vous n'avez rien à faire. C'est très efficace même pour un grand nombre de rangées

31
Thomas Levesque

Je pense que vous pouvez utiliser la méthode DataReader au lieu de DataAdapter . DataReader est un composant oneway très efficace, car il ne lit que les données de la source et vous pouvez remplir une table de données avec une boucle.

6
Nanda

Si vous avez une quantité énorme de lignes, comme 10 000 et plus,

pour éviter toute perte de performances, procédez comme suit avant de lier les données:

dataGridView1.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.EnableResizing; 
//or even better .DisableResizing. 
//Most time consumption enum is DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders
dataGridView1.RowHeadersVisible = false; // set it to false if not needed

après la liaison de données, vous pouvez l'activer.

2
okarpov

Essayez d'utiliser un DataTable. Remplissez-le ..__ Ensuite, utilisez un DataView. Attribuez-le à DataGridView DataSource. 

//DataView dataView = new DataView(dataTable);
//this.Grid.DataSource = dataView;

Vous obtiendrez des temps de réponse très PETIT pour les gros fichiers (25 000 enregistrements et 21 colonnes en une seconde) . Mon programme de modèle a pris 7 secondes pour charger 100 000 lignes * 100 colonnes {Avec des contenus stupides -> numéro de ligne chaîne}

1
C. Lorphelin

cela a résolu mon problème:

array<DataGridViewRow^>
    ^theRows = nullptr;
if (DG->Rows->Count == 0)//First Compilation
{
    int NUMROWS = xxx;
    theRows = gcnew array<DataGridViewRow^>(NUMROWS);
    for (int nr = 0; nr < DRH->Count; nr++)
        theRows[nr] = gcnew DataGridViewRow();
//Do not remove the two following
    DG->Rows->AddRange(theRows);
    DG->Rows->Clear();
}
else //Update
{

    theRows = gcnew array<DataGridViewRow^>(DG->Rows->Count);
    DG->Rows->CopyTo(theRows, 0);
    DG->Rows->Clear();

}
for(int nr=0;nr<theRows->Length;nr++)
{
    theRows [nr]->SetValues("val1", "val2");
}
DG->Rows->AddRange(theRows);
1
user2525774

Je ne suis pas sûr que ce soit ce que vous demandez, mais j'aime bien créer un sous-ensemble de données à charger initialement, puis inclure la fonctionnalité de recherche .. C'est très facile à faire avec Visual Studio 15 et DataSources/data. sets . Dans l'explorateur de solutions, ouvrez votre fichier dataset.xsd. Il sera nommé DataSet.xsd Accédez à la table de données en question. Cliquez avec le bouton droit et ajoutez une requête. Une chose que je fais habituellement est d’ajouter simplement "TOP 1000" à ma requête . Ainsi, select * de mytable devient select TOP 1000 * de mytable

Enfin, double-cliquez sur votre formulaire pour rechercher votre méthode _load et modifiez le champ "Remplir" pour utiliser votre nouvelle requête. Cela pourrait être mieux démontré avec un exemple:

La première ligne de code que j'ai commentée est ce que Vis Stud a créé par défaut . La seconde est celle que j'ai ajoutée, qui obtiendra uniquement les 1000 meilleurs enregistrements.

        private void Form_Customers_Load(object sender, EventArgs e)
    {
        // TODO: This line of code loads data into the 'stage2DataSet.customers' table. You can move, or remove it, as needed.
        /* this.customersTableAdapter.Fill(this.stage2DataSet.customers); */
        this.customersTableAdapter.FillBy_Top_1000(this.stage2DataSet.customers);


    }
0
Joe Hayes