Hallo!
Ich arbeite gerade mit dem Visual Studio 2005 und den SQL Server Express 2005! Ich baue mir gerade eine Programm zur Verwaltung von Artikeln usw. auf. Auf einer Form habe ich nun ein DataGridView indem ich meine ganzen Datensätze anzeigen lasse. Die Verbindung zur Datenbank stelle ich folgendermaßen im "Form_Load" her:
sConnectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Datenbank.mdf;Integrated Security=True;User Instance=True";
con = new SqlConnection(sConnectionString);
cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandText = "SELECT * FROM tbl_Artikel";
ds = new DataSet();
da = new SqlDataAdapter(cmd);
con.Open();
da.Fill(ds, "Artikel");
con.Close();
ArtikelBindingSource.DataSource = ds;
ArtikelBindingSource.DataMember = "Kunden";
ArtikelBindingSource.Sort = "Name ASC, Vorname ASC, Strasse ASC";
dgvArtikel.DataSource = ArtikelBindingSource;
Nun zu meiner Frage, da ich noch nicht lange so lange mit Datenbanken arbeite: Ist 1. dieser Weg so in Ordnung und 2. ich habe zu Testzwecken mal knapp über 100 Datensätze erstellt und dabei braucht er schon, wenn er sie zum ersten Mal lädt so 10 oder mehr Sekunden. Kann man irgendwie das Laden und Anzeigen der Daten im DataGridView beschleunigen? Denn es sollte bei dieser Tabelle schon so auf 5000 Datensätze hinauslaufen!
Vielen Dank schonmal im Voraus!
Gruß
Echo
Hallo,
der Ansatz ist eher schlecht, wie Du ja auch schon gemerkt hast.
Der erste Abruf aus einer DB dauert immer etwas länger, weil NET zuerst die Verbindung herstellen muss. Bei späteren Aufrufen geht es in aller Regel schneller, weil dann die DbConnection aus dem ConnectionPool - siehe :rtfm: Verbindungspooling - geholt werden kann.
In aller Regel solltest Du Dir immer nur die Daten holen, die wirklich benötigt werden - also nicht alle Kunden und alle Artikel "auf Vorrat", sondern durch geeignete WHERE-Klauseln nur "nach Aufforderung" einen oder ein paar Datensätze. Es bringt dem Anwender meistens nicht viel, wenn er z.B. in einem DataGridView durch 1000 Datensätze scrollen muss...
Für das "blockweise Laden" gibt es übrigens mehrere Diskussionen; bitte die Suche benutzen.
Ausnahmen gelten allenfalls bei "Nachschlagetabellen". Wie das dann geregelt wird, hängt vom Einzelfall ab. (Andreas Kosch hat z.B. für eine Client/Server-Anwendung vorgeschlagen, sogar die PLZ/Orte-Tabelle mit etwa 100.000 Datensätzen lokal als Xml-Datei zu speichern und per ReadXml beim Programmstart zu laden, aber nicht jedesmal per SELECT aus der DB zu holen.)
Ich hoffe, Dir helfen diese Hinweise etwas. Jürgen
Danke für deine Antwort!
Meine bisherige Vorgehensweise war ja, dass ich mein Programm starte und ich diese Verbindung erst aufbaue, wenn der Benutzer einen bestimmten Menüpunkt aufruft. Sollte ich jetzt lieber die Verbindung schon beim Programmstart aufrufen und dann beim Auswählen des Menüpunkts nur noch die Daten reinholen?
Programmstart: Herstellen und öffnen der Verbindung!
sConnectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Datenbank.mdf;Integrated Security=True;User Instance=True";
con = new SqlConnection(sConnectionString);
con.Open();
con.Close();
Menüpunktaufruf: Aufrufen der Daten!
cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandText = "SELECT * FROM tbl_Artikel";
ds = new DataSet();
da = new SqlDataAdapter(cmd);
con.Open();
da.Fill(ds, "Artikel");
con.Close();
ArtikelBindingSource.DataSource = ds;
ArtikelBindingSource.DataMember = "Kunden";
ArtikelBindingSource.Sort = "Name ASC, Vorname ASC, Strasse ASC";
dgvArtikel.DataSource = ArtikelBindingSource;
Wenn das so richtig sein sollte und ich auch verstanden habe, wie bekomme ich aber beim "Aufruf der Daten" den Zugriff auf mein ConnectionObjekt, welches ich dem "SqlCommand" zuweise und vor dem "da.Fill" öffne?
Gruß
Echo
Meine bisherige Vorgehensweise war ja, dass ich mein Programm starte und ich diese Verbindung erst aufbaue, wenn der Benutzer einen bestimmten Menüpunkt aufruft. Sollte ich jetzt lieber die Verbindung schon beim Programmstart aufrufen und dann beim Auswählen des Menüpunkts nur noch die Daten reinholen?
Nein; es ist schon korrekt, dass die Verbindung nur bei Bedarf geöffnet wird und nach Ende eines Befehls wieder geschlossen wird. Der DbDataAdapter öffnet und schließt übrigens meistens automatisch.
Ausnahme: Beim Programmstart kann (wie Du es gemacht hast) geprüft werden, ob die Verbindung überhaupt möglich ist.
Menüpunktaufruf: Aufrufen der Daten!
cmd = new SqlCommand(); cmd.Connection = con; cmd.CommandText = "SELECT * FROM tbl_Artikel";
In dieser Form in aller Regel falsch: nicht alle Daten holen, sondern nur die im Moment wirklich gewünschten! Es fehlt also vor allem eine WHERE-Klausel. (Sind denn in der Tabelle "Artikel" wirklich die Kundendaten enthalten? Das wäre eigentlich widersinnig.)
Wenn das so richtig sein sollte und ich auch verstanden habe, wie bekomme ich aber beim "Aufruf der Daten" den Zugriff auf mein ConnectionObjekt, welches ich dem "SqlCommand" zuweise und vor dem "da.Fill" öffne?
Theoretisch könntest Du Dir die con-Instanz "irgendwo" merken und jedesmal holen. Tatsächlich wird eher so gearbeitet:
using(DbConnection con = new DbConnection(myConnString)) {
// erzeuge DbCommand, verbinde ihn mit con, hole die Daten
}
Nur der ConnectionString wird irgendwo registriert. Argumente bekommst Du z.B. über die Forumssuche: Bereich "Datentechnologie", Suchbegriff "ConnectionString", Autor "FZelle" - siehe Eine Verbindung für das gesammte Programm?
Gruß Jürgen
PS. Ich bitte darum, Deinen Nickname zu ändern (d.h. über die Moderatoren): Die Klammern '[' und ']' bringen die Anzeige von Zitaten durcheinander.