2017-09-25 6 views
0

le domaine de problème est que j'ai un fichier db avec comme ~ 90000 lignes et 6 colonnes. J'ai obtenu une requête Select où je reçois toutes les lignes et colonnes qui me sont nécessaires et cela fonctionne bien. Maintenant, c'est la chose que je remplis un DataTable avec ces enregistrements. Je fais cela avec SQliteDataAdapter Fill Method et cela prend environ ~ 1,3 secondes et après cela, je remplis mon ObservableCollection (< - Back to DataGrid) avec ces données et cela prend environ ~ 1,3 secondes. Donc, voici mon codeC# SQLiteDataAdapter Fill Method est lent

private void GetSelectedMaterial() 
    { 
     DataTable dtMaterial = new DataTable(); 
     materialColl.Clear(); // Clearing ObservableCollection 

     Trace.WriteLine("GetSelectedMaterial TS " + DateTime.Now + DateTime.Now.Millisecond); 
     using (SQLiteConnection connection = new SQLiteConnection(dbConnection)) 
     using (SQLiteCommand cmd = connection.CreateCommand()) 
     { 
      connection.Open(); 

      query = "SELECT * FROM Tbl_Materialliste LEFT JOIN(SELECT * FROM Tbl_Besitzt k WHERE k.TechnikID = '" + teTechnikID + "') as k ON k.MaterialID = Tbl_Materialliste.MaterialID"; 

      dataAdapter = new SQLiteDataAdapter(query, connection); 
      Trace.WriteLine("query: " + DateTime.Now + DateTime.Now.Millisecond); 

      dtMaterial.Columns.Add("Checked", typeof(bool)); 
      Trace.WriteLine("here comes the fill: " + DateTime.Now + DateTime.Now.Millisecond); 
      dataAdapter.Fill(dtMaterial); 

      Trace.WriteLine("Checkbox: " + DateTime.Now + DateTime.Now.Millisecond); 
      DetermineCheckBox(dtMaterial, teTechnikID, 8); 
      Trace.WriteLine("SQL TS: " + DateTime.Now + DateTime.Now.Millisecond); 
     } 

     FillMaterialColl(dtMaterial); 
    } 

    private void FillMaterialColl(DataTable dtMaterial) 
    { 
     foreach (DataRow dr in dtMaterial.Rows) 
     { 
      Material mat = new Material(); 

      mat.isChecked = (bool)dr.ItemArray[0]; 
      mat.materialID = (string)dr.ItemArray[1]; 
      mat.materialkurztext = (string)dr.ItemArray[2]; 
      mat.herstellername = (string)dr.ItemArray[3]; 
      mat.herArtikenummer = (string)dr.ItemArray[4]; 
      mat.dokument = (string)dr.ItemArray[5]; 
      mat.substMaterial = (string)dr.ItemArray[6]; 

      materialColl.Add(mat); 
     } 
    } 

Je sais que ObservableCollections drainent les performances, mais est-il possible de le faire d'une autre manière? Certains disent d'utiliser DataReader au lieu de DataAdapter mais DataAdapter doit utiliser DataReader donc je pense qu'il n'y a pas d'amélioration dans les performances. Le problème principal est que ce processus prend trop de temps et l'expérience utilisateur n'est pas si bon, si montrant du nouveau matériel prend environ 3-4 secondes ..

EDIT vient donc ici ma conception de DB: enter image description here

Il s'agit d'une relation many-to-many entre Tbl_Material et Tbl_Technik Et ma requête Select me donne TOUTES les entrées de Tbl_Material (~ 90k) et en plus ces colonnes de Tbl_Besitzt où je peux trouver le technikID Pour que je puisse filtrer (pour une case à cocher) qui entrys appartiennent à mon MaterialID Dans mon fichier DB MaterialId de Tbl_Materiallis Te est un PK et aussi TechnikID de Tbl_Technik - pas que vous vous demandez dans l'image de conception, je n'ai pas compris dans le modèle ..

Merci beaucoup!

+0

Oui c'est vrai, mais ça ne change pas si je le fais sans fil arrière ... Je vais éditer mon code pour que le fil ne soit pas nécessaire ... d'autres idées d'aide? – user8574993

Répondre

0

Il est difficile d'étudier les problèmes de performances d'une base de données sans connaître son schéma et sa conception. Dans votre requête SQL, il existe une expression join. Vous devez vous assurer que les champs de données correspondants sont indexés afin de rendre l'opération de jointure rapide. Cela dépend également de la taille des données de les deux tables. Pour accélérer l'affichage des résultats de la recherche, vous devez éviter de les ajouter article par article dans votre ObservableCollection<T>. En effet, chaque fois que vous ajoutez un nouvel élément, le moteur de liaison transfère cet élément au DataGrid, ce qui oblige la grille à effectuer toutes les actions dont elle a besoin pour afficher un enregistrement.

Si vous ne avez pas vraiment besoin de cette collection pour être observable (par exemple, vous n'ajouter ou supprimer des éléments de la vue), puis il suffit de se rendre à un IEnumerable<T>:

public IEnumerable<Material> Materials 
{ 
    get { return this.materials; } 
    private set 
    { 
     // Using the PRISM-like implementation of INotifyPropertyChanged here 
     // Change this to yours 
     this.SetProperty(ref this.materials, value); 
    } 
} 

En vous méthode , créez un List<Material> local, le remplir, puis exposer à la vue:

List<Material> materials = new List<Material>(); 
// fill the list here 
// ... 
// finally, assign the result to your property causing the binding to do the job once 
this.Materials = materials; 

Si vous avez besoin si ObservableCollection<T>, vous pouvez faire la même astuce - créer une copie locale, le remplir, et enfin exposer.

Si cela ne vous aide pas, essayez d'utiliser la virtualisation de l'interface utilisateur. C'est un sujet plutôt important, mais il y a beaucoup d'informations sur le net.

+0

Je l'ai changé comme vous l'avez décrit et maintenant c'est comme ~ 250ms pour le remplissage de la liste! Merci beaucoup! Je vais éditer mon post afin que vous puissiez voir mon design db alors peut-être que vous pouvez jeter un oeil? – user8574993