Autor Beitrag
Fonsi
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Mi 23.03.11 16:09 
Hallo liebe C#-Community,

ich bin neu hier im Forum. Was die Programmierung mit C# angeht auch, allerdings fiel mit der Umstieg von VB.Net nicht sonderlich schwer.

Ich habe folgendes Problem: In eine Tabelle (t_trainingsplan) meiner Access-Datenbank wird ein Datensatz eingefügt:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
        public void TrainingsplanEinfuegen(int WochentagNr, int SportartNr, int Saetze, int Wiederholungen, double Dauer)
        {
            this.cmd.CommandText = @"INSERT INTO t_trainingsplan (WochentagNr, SportartNr, Saetze, Wiederholungen, Dauer)" +
                       @"VALUES (@WochentagNr, @SportartNr, @Saetze, @Wiederholungen, @Dauer);";

            this.cmd.Parameters.Add("@WochentagNr", OleDbType.Integer).Value = WochentagNr;
            this.cmd.Parameters.Add("@SportartNr", OleDbType.Integer).Value = SportartNr;
            this.cmd.Parameters.Add("@Saetze", OleDbType.Integer).Value = Saetze;
            this.cmd.Parameters.Add("@Wiederholungen", OleDbType.Integer).Value = Wiederholungen;
            this.cmd.Parameters.Add("@Dauer", OleDbType.Double).Value = Dauer;

            this.cmd.ExecuteNonQuery();
        }


Das funktioniert nach dem Programmstart beim ersten Insert problemlos. Jedoch wird danach bei jedem weiteren Insert (der Nutzer kann sich einen Trainingsplan zusammenstellen, indem er bestimmte Sportarten den Wochentagen zuordnen kann...) immer der gleiche erste Datensatz wieder eingefügt. Und das, obwohl die Parameter beim Debuggen die vom Nutzer ausgewählten korrekten Werte besitzen.

Kennt jemand das Problem bzw. kann mir wer helfen? :?

Edit: Ich hab nun herausgefunden, dass es wohl an den Parametern liegt. Ich habe im Hauptformular eine globale Variable "AccDb" vom Typ Datenbank. Die Datenbank-Klasse hab ich selbst geschrieben. Darin befindet sich auch die Funktion "TrainingsplanEinfuegen", die nach Klicken eines Buttons aufgerufen wird. Wenn ich diese erweitere um:
this.cmd.Parameters.Clear();
funktioniert alles, wie es soll. Ist das Vorgehen so in Ordnung? Oder sollte ich das generell anders lösen?
Trashkid2000
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 561
Erhaltene Danke: 137



BeitragVerfasst: Mi 23.03.11 20:21 
Hallo Fonsi und :welcome:

also das mit dem Parameters.Clear() geht natürlich, ist aber nicht die sauberste Lösung.
Den Command solltest Du in einen using-Block packen und immer wieder neu erstellen. Und das gilt eigentlich auch für die Connection! Also in etwa so:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
using (OleDbConnection conn = new OleDbConnection(connStr))
{
  conn.Open();
  string cmdText = "INSERT INTO t_trainingsplan (WochentagNr, SportartNr, Saetze, Wiederholungen, Dauer)" +
                   "VALUES (@WochentagNr, @SportartNr, @Saetze, @Wiederholungen, @Dauer);";
  using (OleDbCommand cmd = new OleDbCommand(cmdText, conn))
  {
    cmd.Parameters.AddWithValue("@WochentagNr", WochentagNr);
    ...
    cmd.ExecuteNonQuery();
  }
}
So wäre es eine saubere Lösung.
LG, Marko
Fonsi Threadstarter
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Do 24.03.11 08:37 
Hallo und danke für den Tipp!

Es ist ne Single User-Anwendung und die Datenbank befindet sich immer direkt lokal beim auszuführenden Programm.
Daher kann auf Grund der besseren Performance die Verbindung zur Datenbank eigentlich während der Ausführung des Programms immer geöffnet bleiben :wink:
Trashkid2000
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 561
Erhaltene Danke: 137



BeitragVerfasst: Do 24.03.11 21:19 
Hi,
user profile iconFonsi hat folgendes geschrieben Zum zitierten Posting springen:
Daher kann auf Grund der besseren Performance die Verbindung zur Datenbank eigentlich während der Ausführung des Programms immer geöffnet bleiben
Naja, auch OleDb nutzt Connection Pooling. Das bedeutet, dass Du warscheinlich nicht wirklich einen Geschwindigkeitsunterschied feststellen wirst.

Wenn Du dagegen mehrere Datensätze auf einmal (also nacheinander) einfügen willst, so kannst Du die Verbindung natürlich immer wieder verwenden und danach disposen.
Soviel erstmal,
Marko
stendate
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19
Erhaltene Danke: 1



BeitragVerfasst: Do 24.03.11 22:39 
user profile iconTrashkid2000 hat folgendes geschrieben Zum zitierten Posting springen:
Hi,
user profile iconFonsi hat folgendes geschrieben Zum zitierten Posting springen:
Daher kann auf Grund der besseren Performance die Verbindung zur Datenbank eigentlich während der Ausführung des Programms immer geöffnet bleiben

Naja, auch OleDb nutzt Connection Pooling. Das bedeutet, dass Du warscheinlich nicht wirklich einen Geschwindigkeitsunterschied feststellen wirst.


Doch, das mit dem Pool bringt nur was wenn auch Connections im Pool drin sind. Wird für einige Sekunden keine Connection gebraucht ist der Pool auch wieder leer und ich verliere Performance beim Reconnect. Es hängt also schon von der Anwendungslogik ab ob man sich auf Connection-Pooling verlassen möchte oder nicht.

Die Sache mit dem Using-Block um das OleDbCommand-Objekt ist aber unabhängig davon schon zu empfehlen, außer es handelt sich um eine "große" Schleife die ein paar tausend mal durchlaufen wird (man will na nicht ein paar tausend mal den GC durch das Dispose() aufrufen lassen blos weil der Code schöner aussieht).
Fonsi Threadstarter
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Di 29.03.11 11:41 
Mit dem Connection Pool hab ich mich auch auseinander gesetzt und hab mich dann für diese Anwendung dazu entscheiden, dass die Verbindung zur Datenbank immer geöffnet bleibt.

Sollte man dann das OleDbCommand-Objekt mit dem Using-Block nutzen?
Derzeit ist das OleDbCommand als private Variable meiner Klasse Datenbank deklariert und wird dort auch initialisiert:
ausblenden C#-Quelltext
1:
private OleDbCommand cmd = new OleDbCommand();