Announcement

Collapse
No announcement yet.

DataGrid Veränderungen übernehmen?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • DataGrid Veränderungen übernehmen?

    Hallo zusammen,
    ich arbeite mit VisualStudio 2005 (c++), Firebird 2.0, FirebirdClient 2.0, DDEXProvider 2.0 und einer Datenbank vom Typ FDB.

    Ich lese aus meiner Datenbank alle Daten aus meiner Tabelle "KUNDEN" und schreibe sie in ein DataGrid(mit Hilfe der tools: fbconnection, fbDataAdapter und eines DataSets).

    CODE:
    fbConnection1->Open();
    fbDataAdapter1->Fill(dataSet1,"KUNDEN");
    dataGrid1->DataSource = dataSet1;
    this->dataGrid1->DataMember = dataSet1->Tables["KUNDEN"]->TableName;
    fbConnection1->Close();

    In diesem Grid kann ich die Daten alle verändern (genau wie ich es will). Nur wie kann ich die Veränderungen die ich im DataGrid gemacht habe in meine Datenbank schreiben?
    Im Prinzip will ich einfach den Inhalt des DataGrids in mein DataSet schreiben und den Inhalt des DataSets in meine Datenbank übernehmen!
    Ich hab schon gelesen das ich dafür SQL Anweisungen schreiben muss .. nur weiß ich nicht wie!? Ich weiß ja vorher nicht was im DataGrid verändert wird .. also wie soll ich da eine bestimmte SQL Anweisung schreiben? Oder is dies gar nicht nötig?

  • #2
    Hallo,

    zunächst bitte ich darum, Code auch als solchen zu markieren mit dem #-Button; das liest sich erheblich besser. Dann ist es wichtig, die richtigen Klassen zu nennen: Arbeitest Du wirklich mit DataGrid und nicht mit DataGridView? Wenn DataGrid, dann WinForms oder WebForms? (Das ist zwar eigentlich für die DB-Verarbeitung unwichtig, aber die DB-Anbindung läuft unter WebForms anders als unter WinForms.)

    Zum Speichern von "beliebigen" Änderungen ist DbDataAdapter.Update zuständig. Eine Anleitung findest Du unter openbook visual C# Kap.25 ff. Du musst nur anstelle der dort benutzten Sql-Klassen die Fb-Klassen verwenden.

    Übrigens solltest Du Dir merken:
    Im Prinzip will ich einfach den Inhalt des DataGrids in mein DataSet schreiben und den Inhalt des DataSets in meine Datenbank übernehmen!
    Unter ADO.NET wird getrennt zwischen Daten im Arbeitsspeicher und GUI. Bearbeitet werden Daten in DataSet/DataTable; diese sind in die DB zu übernehmen. Die Verbindung DataSet und DataGrid findet automatisch durch DataSource/DataMember statt.

    Gruß und Frohes Neues Jahr! Jürgen

    /Nachtrag
    Danke, Christian, für diesen Hinweis. Also ist meine Frage erst recht wichtig: Geht es um WinForms oder um WebForms? (Hätte mir aber auch auffallen können...)
    Zuletzt editiert von Jürgen Thomas; 03.01.2009, 18:23.

    Comment


    • #3
      http://entwickler-forum.de/showthrea...511#post184511
      Christian

      Comment


      • #4
        Hallo Jürgen,
        tut mir leid mit dem Quellcode, bin noch relativ neu hier aber werd es mir zu Herzen nehmen
        Ich arbeite mit dem DataGrid in einer WinForm.

        Zum Speichern von "beliebigen" Änderungen ist DbDataAdapter.Update zuständig. Eine Anleitung findest Du unter openbook visual C# Kap.25 ff. Du musst nur anstelle der dort benutzten Sql-Klassen die Fb-Klassen verwenden.
        Ich finde leider unter dem Link den du mir geschickt hast nichts zu DbDataAtapter.Update !
        Aber ich habe schon ein bischen was in diese Richtung gemacht, da ich auch andere Beispiele gefunden habe die so ähnlich waren

        Ich habe es jetzt folgendermaßen probiert:

        Code:
        this->fbConnection1->Open();
        dataSet1->Tables["KUNDEN"]->TableName=this->dataGrid1->DataMember;
        this->fbDataAdapter1->Update(dataSet1,"KUNDEN"); 
        this->fbConnection1->Close();
        Meiner Meinung nach speicher ich jetzt den Inhalt meines DataGrids in mein DataSet. Also müssten in dem DataSet ja jetzt auch alle Veränderungen die ausgeführt wurden vorhanden sein?! Oder denk ich da falsch?
        Danach mache ich ein Update meines DataAdapter. Und zwar um das DataSet, was ja jetzt eigentlich alle Veränderungen beinhalten müsste.
        Ansich zeigt mir mein Programm auch kein Fehler an beim neu erstellen. Führ ich das Programm aber aus und drücke auf den Button der den oben genanten CODE ausführt kommt folgende Fehlermeldung:

        Eine nicht behandelte Ausnahme des Types "FirebirdSql.Data.FirebirdClient.FbException" ist in FirebirdSql.Data.FirebirdClient.dll aufgetreten.

        Zusätzliche Informationen: Dynamic SQL Error
        SQL error code = -104
        Token unknown - line 1, char 47
        üller

        Comment


        • #5
          Originally posted by MarcoOoOo View Post
          Ich arbeite mit dem DataGrid in einer WinForm.
          Na endlich. Dann ist die Frage in ASP.NET hinfällig.

          Ich finde leider unter dem Link den du mir geschickt hast nichts zu DbDataAtapter.Update !
          DbDataAdapter ist die Basis-Klasse. Davon abgeleitet sind verschiedene Klassen; je nach DB und DbProvider muss eine der abgeleiteten Klassen verwendet werden.

          Im OpenBook werden Sql-Klassen verwendet, Du musst Fb-Klassen verwenden. Also suche im Link oder in der SDK-Doku/MSDN nach SqlDataAdapter.

          Code:
          this->fbConnection1->Open();
          dataSet1->Tables["KUNDEN"]->TableName=this->dataGrid1->DataMember;
          this->fbDataAdapter1->Update(dataSet1,"KUNDEN"); 
          this->fbConnection1->Close();
          Das sieht teilweise brauchbar aus. Der FbDataAdapter benötigt Insert-, Update- und DeleteCommand; aus dem SelectCommand kann er diese u.U. selbst erzeugen.

          Aber diese Zuordnung ist Quatsch:
          Code:
          dataSet1->Tables["KUNDEN"]->TableName=this->dataGrid1->DataMember;
          Die Tabelle heißt doch schon "KUNDEN". Wieso willst Du ihr die DataMember des DataGrid zuordnen? Diese Zeile ist nur beim Einlesen (also bei der Fill-Methode) relevant, aber muss dann umgekehrt lauten:
          Code:
          dataGrid1->DataMember = "KUNDEN";
          Meiner Meinung nach speicher ich jetzt den Inhalt meines DataGrids in mein DataSet.
          Bitte vergiss schnellstens diese Vorstellung! Die Inhalte des DataGrids werden automatisch im DataSet gespeichert. Du willst die Änderungen vom DataSet in die Datenbank übertragen. Dazu dient der Update-Befehl.

          Ansich zeigt mir mein Programm auch kein Fehler an beim neu erstellen. Führ ich das Programm aber aus und drücke auf den Button der den oben genanten CODE ausführt kommt folgende Fehlermeldung:
          Welchen Code meinst Du genau mit "oben genannten"? Den gerade zitierten? Was ist denn Zeile 47?

          Wenn Du schon weißt, dass eine Exception kommt, dann bau doch try-catch um diesen Bereich herum. Mit Exception.ToString() bekommst Du noch mehr Informationen als mit Exception.Message.

          Gruß Jürgen

          Comment


          • #6
            Bitte vergiss schnellstens diese Vorstellung! Die Inhalte des DataGrids werden automatisch im DataSet gespeichert. Du willst die Änderungen vom DataSet in die Datenbank übertragen. Dazu dient der Update-Befehl.
            Ich versteh nicht ganz wie es gehen soll, dass die Inhalte des DataGrids automatisch im DataSet gespeichert werden?!?
            Als ich die Daten aus der Datenbank ins Grid gelesen hatte, müsste ich das Grid doch auch direkt mit dem DataSet in Verbindung bringen ...

            Code:
            fbConnection1->Open();
            fbDataAdapter1->Fill(dataSet1,"KUNDEN");
            dataGrid1->DataSource = dataSet1;
            this->dataGrid1->DataMember = dataSet1->Tables["KUNDEN"]->TableName;
            fbConnection1->Close();
            wenn ich die Daten wieder in die Datenbank schreiben will, muss ich doch auch mein verändertes DataSet irgendwo einbinden?!?



            Aber wenn es stimmt, dass es automatisch geht, muss es doch eigentlich reichen wenn ich nur den Updatebefehl benutze ..
            also:
            Code:
            this->fbDataAdapter1->Update(dataSet1,"KUNDEN");
            aber nur der Code reicht anscheinend nicht, da ich dann, wie im letzten Beitrag von mir geschrieben, eine Fehlermeldung bekomme.




            Der FbDataAdapter benötigt Insert-, Update- und DeleteCommand; aus dem SelectCommand kann er diese u.U. selbst erzeugen.
            Insert-, Update- und DeleteCommand hab ich bei mir nicht deklariert ... weil ich mir nicht vorstellen kann, wie diese aussehen sollen ... da ich ja meine Datenbank in ein Grid lade und dort von Benutzern verändern lassen möchte. Ich weiß ja aber nicht was diese dann dort verändern, also kann ich doch auch keine Insert-, Update- und DeleteCommands schreiben?!?


            mit dem "oben genanten Code" meinte ich:
            Code:
            this->fbConnection1->Open();
            dataSet1->Tables["KUNDEN"]->TableName=this->dataGrid1->DataMember;
            this->fbDataAdapter1->Update(dataSet1,"KUNDEN"); 
            this->fbConnection1->Close();
            Wenn Du schon weißt, dass eine Exception kommt, dann bau doch try-catch um diesen Bereich herum. Mit Exception.ToString() bekommst Du noch mehr Informationen als mit Exception.Message.
            Also ich bin noch ganz neu im Programmieren und versuch mir das grad alles selbst irgentwie verständlich zu machen. Mit try-catch habe ich noch nicht wirklich gearbeitet genauso wenig wie mit Exception.ToString()
            Zuletzt editiert von MarcoOoOo; 03.01.2009, 21:05.

            Comment


            • #7
              Hallo Marco,

              also nochmals neu formuliert als einführende Erläuterung (weitgehend ohne Bezug auf Deinen Code). Der folgende Text bezieht sich auf ADO.NET und gilt in gleicher Weise für alle NET-Sprachen, also C#, VB.NET, Prism und C++ (soweit es NET-Klassen benutzt) und was es sonst noch gibt.

              Die Daten befinden sich zunächst fest gespeichert in der Datenbank auf der Festplatte.

              Zusätzlich gibt es eine Kopie von einigen Daten im Arbeitsspeicher. Diese Kopie wird abgelegt im DataSet und dort in einer oder mehreren DataTables. Im Normalfall werden nicht alle Daten geholt, sondern nur einige Nachschlagetabellen (Liste der MWSt-Sätze bis zur Liste aller PLZ/Orte - Letzteres ist ein Grenzfall) und ansonsten immer nur der Kunde, der gerade gesucht wird und bearbeitet werden soll, mit seinen Adressen und Aufträgen.

              Diese Daten werden mit einem oder (meistens) mehreren Select-Befehlen in eine oder mehrere DataTables geholt. Dazu dient der Befehl DbDataAdapter.Fill(). Damit das Speichern von Änderungen einfach geht, sollte jede DataTable von der Struktur her (Felder, Primärindex, Constraints, DataRelations/ForeignKeys) genau einer DB-Tabelle entsprechen.

              Diese DataTables werden als Datenquelle gebunden an GUI-Elemente (DataGrid, DataGridView, auch TextBox usw.). Vor allem wenn eine BindingSource dazwischengeschaltet wird, kann auch in der Datenmenge navigiert werden.

              Änderungen eines Anwenders in einem dieser "angebundenen" Controls werden automatisch (wirklich!) in der jeweiligen DataTable gespeichert; allenfalls muss noch EndEdit() eingefügt werden. Änderungen per Code werden nur in DataTable.Rows vorgenommen. Die Änderungen stehen unmittelbar in den Controls zur Verfügung; allenfalls muss noch etwas wie Refresh() eingefügt werden.

              Damit die Änderungen auch in der Datenbank landen, muss eine neue DbConnection mit DbDataAdapter und DbCommand aufgebaut werden und mit DbDataAdapter.Update() ausgeführt werden. Wenn dieser DbDataAdapter einen SelectCommand mit PrimaryKey erhält, kann er Update/Insert/DeleteCommand selbständig erstellen.

              Bevor ich alles wiederhole: Bitte arbeite ein Buch zur DB-Anbindung unter NET durch. Mein Vorschlag ist OpenBook Visual C# Kap.25 ff.

              Merke: Unter ADO.NET wird getrennt zwischen Datenbank auf der Festplatte, Datenmenge im Arbeitsspeicher und Anzeige/Eingabe in der GUI. Die Verknüpfung der Daten findet durch DbConnection, DbDataAdapter, DbCommand u.ä. statt. Die Übergabe an die Anzeige findet durch DataSource bei den Controls statt (automatisch in beide Richtungen).

              Eine DbConnection ist immer nur kurzfristig zu öffnen und dann zu schließen und mit Dispose aufzulösen. NET arbeitet automatisch mit ConnectionPooling.

              Wenn ich von Db-Klassen schreibe, sind immer die Klassen des benutzten DbProviders zu verwenden: Sql für MS-SQL, MySql für MySql, Fb für Firebird usw.

              Noch als konkrete Hinweise: try-catch ist eine grundlegende Technik; die musst Du schnellstens berücksichtigen und an kritischen Stellen einbauen. Wenn Du AcceptChanges in Deinem Code hast, dann schmeiß diesen Befehl sofort raus - der dürfte dann dafür verantwortlich sein, dass nicht gespeichert wird. (Benutze die Forumssuche nach diesem Begriff für weitere Erläuterungen.)

              Trotz der vielen Hinweise viel Erfolg! Jürgen

              Comment


              • #8
                Hallo Jürgen,
                also erstma danke für die Zeit die du dir für mich genommen hast. Ich glaube ein bisschen schlauer bin ich schon geworden ^^.

                Aber eine letzte Frage hab ich noch, dann lass ich dich auch in Ruhe.

                Wenn ich den Befehl:
                Code:
                fbDataAdapter1->Update(...)
                benutzen will, muss auf jeden Fall vorher der Update Command erstellt worden sein??? Oder ?!?

                Comment


                • #9
                  Originally posted by MarcoOoOo View Post
                  Wenn ich den Befehl:
                  Code:
                  fbDataAdapter1->Update(...)
                  benutzen will, muss auf jeden Fall vorher der Update Command erstellt worden sein??? Oder ?!?
                  Tut mir leid, ich muss mit einem klaren Jein antworten. Zum einen benötigt die Update-Methode auch einen InsertCommand und einen DeleteCommand. Zum anderen kann der DbDataAdapter sie sich auch selbst erstellen, wenn er einen passenden SelectCommand hat; oder Du kannst sie mit einem DbCommandBuilder gezielt erstellen lassen.

                  Gruß Jürgen

                  Comment

                  Working...
                  X