IBDataSet und grid schnellerer zugriff



  • Hallo,

    AdvStringGrid besitzt die Methoden BeginUpdate() und EndUpdate().
    Wenn du Sie wie folgt einsetzt, wird die Liste deutlich schneller erzeugt.

    StringGrid1->BeginUpdate();
    for (int i = 0; !IBDataSet1->Eof; i++, IBDataSet1->Next())
            {
                for (int j = 0; j < IBDataSet1->Fields->Count; j++)
                    {
                        StringGrid1->Cells[j][i] =  IBDataSet1->Fields->Fields[j]->AsString;
                    }
            }	
    StringGrid1->EndUpdate();
    

    Gruß FireBirdSQL



  • Hallo,

    danke für den tipp, aber eine deutliche preformance steigerung is da au net drin!

    IMHO dauert das naviegieren im datensatz zu lange (IBDataSet1->Next()).

    Gibt es nicht eine möglichkeit auf alle datensätze der select anweisung zu zu greifen (d.h. ohne den Zeiger per Next() zu verschieben)? Schließlich liegen ja alle datensätze schon nach der Select anweisung beim client in IBDataSet vor!

    Tia



  • Schließlich liegen ja alle datensätze schon nach der Select anweisung beim client in IBDataSet vor

    Das ist so nicht richtig. Nur wenn IBDataSet->FetchAll() aufgerufen wird werden alle Daten geholt.

    Wie ist das AdvStringGrid initialisiert ? Die Anzahl von Zeilen bzw. Spalten sollte man schon vor dem Füllen mit Daten setzen.

    IBDataSet1->FetchAll();
      int iZeilen = IBDataSet1->RecordCount ;
      int iSpalten = IBDataSet1->Fields->Count;
    
      StringGrid1->BeginUpdate();
    
      StringGrid1->RowCount = iZeilen;   // bei FixedRow = 0;
      StringGrid1->ColCount = iSpalten;  // bei FixedCol = 0;
    
       for (int i = 0; i < iZeilen ; i++)
         for (int j = 0; j < iSpalten ; j++)
                    {
                        StringGrid1->Cells[j][i] =     IBDataSet1->Fields->Fields[j]->AsString;
                    }
       IBDataSet1->Next();
    }
    

    Hast Du mal TDBAdvGrid probiert ?

    Gruß FSQL



  • Also, wenn ich

    IBDataSet1->FetchAll();
      int iZeilen = IBDataSet1->RecordCount ;
      int iSpalten = IBDataSet1->Fields->Count;
    
      StringGrid1->BeginUpdate();
    
      StringGrid1->RowCount = iZeilen;   // bei FixedRow = 0;
      StringGrid1->ColCount = iSpalten;  // bei FixedCol = 0;
    
       for (int i = 0; i < iZeilen ; i++)
         for (int j = 0; j < iSpalten ; j++)
                    {
                        StringGrid1->Cells[j][i] =     IBDataSet1->Fields->Fields[j]->AsString;
                    }
       IBDataSet1->Next();
    }
    

    nutze ist das resultat das selbige (das Naviegieren im Datensatz dauert zu lange)!

    Hast Du mal TDBAdvGrid probiert ?

    Ja damit hat es ja angefangen... das Hauptproblem war eigentlich das ich meine Datensätze immer aktuell wollte (sprich wenn die Datensätze im grid nach Namen sortiert sind sollen diese nach änderungen am client auch sichtbar sein z.B. neuen namen "Bauer" einfügen)! Da wir ja wissen das wenn man einen neuen datensatz hinzufügt dieser am ende steht blieb nur die möglichkeit DataSet zu schließen und wieder zu öffnen!
    Doch das tolle TDBAdvGrid braucht 7 sec um den Datensatz zu öffnen wären ein DBGrid nichmal 1 sec braucht??? 😕
    Das komische jedoch ist das wenn ich mich im builder (nicht zur laufzeit) mit der DB verbinde zeigt TDBAdvGrid die datensätze in > 1 sec an???
    Naja, und was mich absolut vom TDBAdvGrid abgebracht hat ist das es beim grupieren / sortieren eine halbe ewigkeit braucht da ist ein SQL-Statement 1000 mal schneller!

    Hoffe es gibt noch irgend eine möglichkeit mein AdvGrid schnell mit den Daten aus DataSet zu füllen?

    oder nutze ich das TDBAdvGrid einfach nur fasch?

    Tia



  • Wie akari schon gesagt hat, erst mal nur das Anzeigen, was der User im Moment sieht und den Rest dann erst nachladen, wenn der User sich im Grid bewegt.

    Ehrlich gesagt halte ich aber das Anzeigen von 55000 Datensätzen für unsinnig. Niemand will so viele Datensätze sehen. Ich würde ein Filtern der Daten auf eine überschaubare Menge für sinnvoller halten.



  • So, jetzt will ich das so machen wie ihr mir das vorgeschlagen habt (ist auch die schnellste lösung), aber ich finde keinen ansatz wie ich immer nur das ins grid lade was gerade angezeigt wird!?

    Also ich habe die Methode

    void __fastcall TForm1::AdvStringGrid1DrawCell(TObject *Sender, int ACol,
    	  int ARow, TRect &Rect, TGridDrawState State)
    {
    }
    

    Aber immer wenn ich der zelle was zuweise wie:

    void __fastcall TForm1::AdvStringGrid1DrawCell(TObject *Sender, int ACol,
    	  int ARow, TRect &Rect, TGridDrawState State)
    {
    AdvStringGrid1->Cells[1][ARow] = "blaaaa"; 
    }
    

    lande ich in einer verdamten endlos schleife!

    Bitte gebt mir mal nen tip was ich da falsch mache!?

    Tia



  • Das Ereignis DrawCell ist (wie der Name ja sagt), zum grafischen Anzeigen des aktuell zum Grid zugehörigen Text zuständig.
    D.h. wenn du den Text änderst, wird natürlich wieder DrawCell aufgerufen (-> Rekursion).

    Entweder du zeichnest in DrawCell mittels Zugriff auf AdvStringGrid->Canvas den Text von Hand oder aber du benutzt ein anderes Event: OnTopLeftChanged.
    Sobald der Anwender scrollt kopierst du die Daten aus der Datenbank in das StringGrid (natürlich nur soviele Daten wie auch angezeigt werden, d.h. da mußt du ein bißchen mit StringGrid->Height und StringGrid->RowHeights rechnen).



  • Das klingt ja so weit ganz gut, doch wenn ich AdvStringGrid->Canvas benutze kann ich meine ausgabenformatierung vergessen, und wenn ich OnTopLeftChanged nutze weis ich net mehr an welcher stell ich im datensatz bin sobald der user sich mit der scrollBar bewegt!? 😕



  • So,

    habs jetzt über OnTopLeftChanged ,AdvStringGrid->TopRow und nen bissel rumgrechne mit der gid und column höhe gelöst!



  • Super, geht doch 🙂


Anmelden zum Antworten