Entwickler-Ecke

Datenbanken (inkl. ADO.NET) - DataGridView


Sachsenpaule - So 08.05.16 19:52
Titel: DataGridView
Hallo, ich habe ein Problem mit dem ich mich schon längere Zeit beschäftige.
Finde im Netzt zwar immer die Selbe Frage jedoch nie eine Lösung.
Hier mein Problem:
Ich schreibe neue Daten in ein DGV. Die speichere ich mit: adapter.Update(table);
Wenn ich das Fenster schließe und wieder öffne kann ich die Daten Löschen.

C#-Quelltext
1:
2:
3:
4:
5:
6:
foreach (DataGridViewRow item in dataGridView1.SelectedRows)
{
    dataGridView1.Rows.RemoveAt(item.Index);
    dataGridView1.Refresh();
    adapter.Update(table);
}

Wenn ich aber in das DGV neue Daten schreibe und mir auffällt das da was falsch ist
und ich die löschen will ohne das Fenster neu aufzurufen schmiert mir das Programm ab.
Ich hab mir jetzt damit geholfen das ich beim Abspeichern die Datenbank erneut aufmache.
Dann wird von MSSQL eine ID eingetragen und ich kann löschen.
Ich hab nun das Gefühl das ich mir einen Ring durch die Nase gezogen habe.
Hat einer eine Idee?

Moderiert von user profile iconChristian S.: C#-Tags hinzugefügt


Th69 - Mo 09.05.16 09:45

Hallo und :welcome:

bei "schmiert das Programm ab" meinst du sicherlich, daß eine Exception geworfen wird? Dann fange diese mit try...catch ab oder (m.E. noch besser) überprüfe vorher, ob dort eine gültige Id drin steht.


Ralf Jansen - Mo 09.05.16 09:56

Zitat:
Dann wird von MSSQL eine ID eingetragen und ich kann löschen.


Das Insert Command am Adapter kann man auch so schreiben das es die passende Id gleich zurückliefert.


SQL-Anweisung
1:
INSERT INTO MyLovelyTable(MyLovelyValue) VALUES (@MyLovelyValue); SELECT MyLovelyPrimaryKey, MyLovelyValue FROM MyLovelyTable WHERE MyLovelyPrimaryKey = SCOPE_IDENTITY();                    


Sachsenpaule - Mo 09.05.16 12:10

Danke für die schnellen Antworten.
Ja ich habe die Exception abgefangen. Aber das nervt wenn man durch einfaches löschen
eine Fehlermeldung bekommt. Es tritt ja auch nur sehr selten auf. Eben nur dann wenn man
etwas eingibt und direkt wieder löschen will.
Mit dem erneuten Aufruf der Datenbank hab ich mir direkt ein neues Problem eingefangen.
Jedes mal wenn ich etwas übergebe springt der dann auf die erste Zeile des DGV.
Bei langen Datenbanken eine Problem. Aber hatte ich ja schon vermutet.
Ich glaube mit dem SQL das werde ich mal versuchen.
Vielleicht hat noch einer eine Idee wie ich das in C# hinkriegen kann.
Ich muß abspeichern so das die ID direkt ins DGV eingetragen wird und nicht erst nach Neustart.


Sachsenpaule - Mo 09.05.16 12:49

Hab hier meine Aufrauf der DB mal kopiert. Vielleicht ist da ein Fehler drin

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
private void rbViren_CheckedChanged(object sender, EventArgs e)
        {
            databaseOpen("select * from Viren");       // Datenbank öffnen
            tbDatenbank.Text = "Viren";                // Name der Tabelle anzeigen
        }

 private void databaseOpen(string database)
        {
            String connectionString = "Data Source=Obelix;Initial Catalog=Frequenztherapie;Integrated Security=True";
            SqlConnection conn = new SqlConnection(connectionString);
            SqlCommand command = new SqlCommand(database, conn);
            adapter = new SqlDataAdapter(command);
            SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(adapter);      // Damit gespeichert werden kann
            table = new DataTable();
            adapter.Fill(table);
            dataGridView1.DataSource = table;               // Tabelle wird in DataGridView eingelesen
            dataGridView1.Columns[0].Visible = false;       // 1 Spalte wird ausgeblendet
            dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;      // Spaltenbreite wird angepaßt
            tbZaehler.Text = dataGridView1.Rows.Count.ToString();   // Anzahl Datensätze zählen
        }


Moderiert von user profile iconChristian S.: C#-Tags hinzugefügt


Ralf Jansen - Mo 09.05.16 14:53

Fehler nicht aber der Code ist überhaupt nicht am Updaten der Datenbank beteiligt. Der liest nur Daten ein.

a.) der SqlCommandBuilder hier überflüssig
b.) du rufst kein Close/Dispose irgendwas an der Connection auf. Dein Connection bleibt also auf unbestimmte Zeit offen ohne das sie wiederverwendbar wäre. Nicht gut.

Ein Cleanup des Codes (deiner databaseOpen Methode) sähe etwa so aus




C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
private static string connectionString = "Data Source=Obelix;Initial Catalog=Frequenztherapie;Integrated Security=True";

private static DataTable GetDataTable(string selectStatement)
{
    var table = new DataTable();
    using (var conn = new SqlConnection(connectionString))
    {
        using (var adapter = new SqlDataAdapter(connectionString, conn))
        {
            adapter.Fill(table);
        }
    }
    return table;
}

private void databaseOpen(string database)  // übrigens blöder Methoden und Parameterbezeichner
{
    dataGridView1.DataSource = GetDataTable(database);
    dataGridView1.Columns[0].Visible = false;       
    dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;      
    tbZaehler.Text = dataGridView1.Rows.Count.ToString();   
}


Standarddisclaimer : Niemals nie benutze * und schon gar nicht verlasse dich auf die Reihenfolge in der du die Spalten oder Rows deiner Tabelle bekommst. Die einzige Definition bei solch einer Abfrage ist für die Datenbank das es schnell gehen soll. Wenn du keine Reihenfolge bei Zeilen und Spalten festlegst ist die Datenbank frei zu entscheiden welche Reihenfolge sie dir liefert. Was die Datenbank gerade für am schnelssten hält kann sich jederzeit ändern.


Sachsenpaule - Mo 09.05.16 16:21

Danke für die schnelle Hilfe.
Die Bezeichner hatte ich nur zum schnellen Testen benutzt.
Ich teste das mal.
Nochmals Danke. Tolles Forum