Access DB (leer) mit kompletten Typ Dataset befüllen

  • VB.NET

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Access DB (leer) mit kompletten Typ Dataset befüllen

    Obwohl ich weiß dass es die DB Extensions gibt ;) möchte ich lernen wie ich mein typ dataset (die anwendung auf basis xml läuft wie ich es will) in eine access db schaufel.

    mein problem ist derzeit, dass ich hier im forum viele schnipsel/fragmente finde die mir nicht weiterhelfe. meine lektüre geht auf diesen abschnitt auch nicht so ein dass ich es verstehe....

    so weit bin ich bereits dank edr: ich kann eine leere access db erzeugen auf basis des typ datasets, d.h. die beziehungen im typ ds stehen auch in der access db.

    mein problem jetzt: wenn ich mit dem dataadapter.update arbeite werden nicht die "unchanged" rows übertragen (ist ja auch logisch).
    mein ziel ist jedoch die gesamte access db mit allen vorhandenen daten zu befüllen.
    hier mein bisheriger code:

    Quellcode

    1. Dim ofd As New OpenFileDialog
    2. Dim filename As String
    3. ofd.Filter = "SozPraktikum (*.mdb)|*.mdb"
    4. If ofd.ShowDialog = Windows.Forms.DialogResult.OK Then
    5. filename = ofd.FileName
    6. Media.SystemSounds.Asterisk.Play()
    7. Else
    8. MessageBox.Show("Der Dialog wurde abgebrochen")
    9. Return
    10. End If
    11. Dim con As New OleDb.OleDbConnection
    12. con.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & filename
    13. MessageBox.Show(CStr(filename))
    14. con.Open()
    15. Dim adap As New OleDb.OleDbDataAdapter("select * from tblSchüler", con)
    16. Dim builder As New OleDb.OleDbCommandBuilder(adap)
    17. builder.GetUpdateCommand()
    18. adap.Update(DS, "tblSchüler")
    19. con.Close()
    20. end sub


    wie kann ich als ersten step das gesamte DS mit allen Tables in die Access DB schaufeln?

    edit:Schreibfehler
    Gruß Hannes

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „hans im glück“ ()

    Wie kommts, dass du ein Dataset mit Daten hast, die alle unchanged sind, die du aber nicht aus einer DB geladen hast, sonder dort erst noch hineinschaufeln willst?
    Ich kann mir nur vorstellen, du nutzst meine Dataset.Fill - Extension, um ein Dataset DatasetOnly einzulesen.
    Meine Extension führt dann AcceptChanges() aus, und dann sind die Daten unchanged, wie frisch geladene Daten ja normalerweise sind.

    Aber du kannst ebensogut Dataset.ReadXml (standard-Framework-Methode) nehmen, um ein Dataset DatasetOnly einzulesen.
    Dataset.ReadXml führt nicht AcceptChanges aus, und daher stehen dann alle Daten auf Added, und ein DataAdapter würde zulangen beim Daten-Schaufeln.

    Ansonsten gugge auch mol ObjectBrowser: DataRow.SetModified()
    bisher läufts so:
    ds wird mit readxml befüllt. der export nach access ist nur als weitergabe - export eben - gedacht. die egtl. anwedung ist mit readxml glücklich.



    ErfinderDesRades schrieb:

    .....
    Aber du kannst ebensogut Dataset.ReadXml (standard-Framework-Methode) nehmen, um ein Dataset DatasetOnly einzulesen.
    Dataset.ReadXml führt nicht AcceptChanges aus, und daher stehen dann alle Daten auf Added, und ein DataAdapter würde zulangen beim Daten-Schaufeln.

    Ansonsten gugge auch mol ObjectBrowser: DataRow.SetModified()


    aber dann müsste doch mein oben genannter code funktionieren? fakt ist jedoch, dass nur zusätzliche zeilen, also solche die nachträglich (nach ds.readxml) mit bindingsource.addnew hinzugefügt wurden, in die access db übertragen werden.
    Gruß Hannes

    hans im glück schrieb:

    ds wird mit readxml befüllt.
    tja, das sieht man obigem Code nicht an. ;)
    vlt. debuggste das mal sorgfältig, also Haltepunkt direkt nach dem Einlesen, und nachgucken, welchen RowState die Rows haben.

    Dann kannst du noch ObjectBrowser gucken: DataRow.SetModified() - klingt ja nicht unvielversprechend...
    also nun habe ich folgendes hinzu gefügt,

    Quellcode

    1. Dim ofd As New OpenFileDialog
    2. Dim filename As String
    3. ofd.Filter = "SozPraktikum (*.mdb)|*.mdb"
    4. If ofd.ShowDialog = Windows.Forms.DialogResult.OK Then
    5. filename = ofd.FileName
    6. Media.SystemSounds.Asterisk.Play()
    7. Else
    8. MessageBox.Show("Der Dialog wurde abgebrochen")
    9. Return
    10. End If
    11. Dim con As New OleDb.OleDbConnection
    12. con.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & filename
    13. MessageBox.Show(CStr(filename))
    14. For Each rw As DataRow In DS.tblSchüler
    15. If rw.RowState = DataRowState.Unchanged Then
    16. MessageBox.Show("Vorher:" & rw.RowState.ToString)
    17. rw.SetModified()
    18. MessageBox.Show("Nacher:" & rw.RowState.ToString)
    19. End If
    20. Next
    21. con.Open()
    22. Dim adap As New OleDb.OleDbDataAdapter("select * from tblSchüler", con)
    23. Dim builder As New OleDb.OleDbCommandBuilder(adap)
    24. builder.GetUpdateCommand()
    25. adap.Update(DS, "tblSchüler")
    26. con.Close()


    Jetzt zeigt er mir schön bei jeder Zeile / Row wie er von unchanged auf modified geht...


    leider wird in die access db trotzdem nichts übertragen...

    vielleicht habe ich im code bzgl der db einen fehler?
    Gruß Hannes

    ErfinderDesRades schrieb:

    omg!

    Für neue Rows muss man natürlich .SetAdded() aufrufen!

    ungetestet.



    sehr schön, das funktioniert!
    ich habe eine weiter führende frage:

    ich übertrage die tabellen somit derzeit mit folgendem code:

    Quellcode

    1. Dim command As New OleDb.OleDbCommand
    2. command.CommandText = "select * from tblKunden"
    3. Dim adap As New OleDb.OleDbDataAdapter(command.CommandText, con)
    4. Dim builder As New OleDb.OleDbCommandBuilder(adap)
    5. For Each rw As DataRow In DS.tblKunden
    6. If rw.RowState = DataRowState.Unchanged Then
    7. 'MessageBox.Show("Vorher: " & rw.RowState.ToString)
    8. rw.SetAdded()
    9. 'MessageBox.Show("Nacher: " & rw.RowState.ToString)
    10. End If
    11. Next
    12. Try
    13. adap.Update(DS, "tblKunden")
    14. MessageBox.Show("Kunden Tabelle wurde übertragen!")
    15. Catch ex As Exception
    16. MessageBox.Show(ex.Message)
    17. End Try
    18. Dim adap2 As New OleDb.OleDbDataAdapter("select * from tblLagerort", con)
    19. Dim builder2 As New OleDb.OleDbCommandBuilder(adap2)
    20. For Each rw As DataRow In DS.tblLagerort
    21. If rw.RowState = DataRowState.Unchanged Then
    22. rw.SetAdded()
    23. End If
    24. Next
    25. Try
    26. adap2.Update(DS, "tblLagerort")
    27. MessageBox.Show("Lagerort-Tabelle wurde übertragen!")
    28. Catch ex As Exception
    29. MessageBox.Show(ex.Message)
    30. End Try
    31. Dim adap3 As New OleDb.OleDbDataAdapter("select * from tblGeräte", con)
    32. Dim builder3 As New OleDb.OleDbCommandBuilder(adap3)
    33. For Each rw As DataRow In DS.tblGeräte
    34. If rw.RowState = DataRowState.Unchanged Then
    35. 'MessageBox.Show("Vorher: " & rw.RowState.ToString)
    36. rw.SetAdded()
    37. 'MessageBox.Show("Nacher: " & rw.RowState.ToString)
    38. End If
    39. Next
    40. Try
    41. adap3.Update(DS, "tblGeräte")
    42. MessageBox.Show("Geräte-Tabelle wurde übertragen!")
    43. Catch ex As Exception
    44. MessageBox.Show(ex.Message)
    45. End Try
    46. con.Close()



    ...es werden also verschiedene Dataadapter/Commandbuilder erzeugt, es war für mich so einfacher zuerst die Parent Tabellen zu übertragen da die anderen Tabellen ja foreign keys drin haben. Wenn die dann nicht existieren -> schlecht.

    nun habe ich das problem, dass trotzdem der fehler kommt:
    Der Datensatz kann nicht hinzu gefügt werden, da ein Datensatz in der Tabelle 'tblKunden' mit diesem Datensatz in Beziehung stehen muss.


    Die ersten Tabellen werden jedoch fehlerfrei übertragen, in der Access DB sind die Beziehungen ja ebenfalls vorhanden.

    Was kann ich tun?

    Gibt es auch eine möglichkeit alle Tabellen unter Berücksichtigung der Beziehungen zu updaten?
    Gruß Hannes
    Das Prob ist, dass die DB nicht die PrimKeys aussm Dataset übernimmt, sondern eigene generiert.
    Wenn du im folgenden also Untergeordnetes insertest, finden die natürlich ihren Parent nicht in der Db und bäng.
    Man muss also nach jedem einzelnen inserteten Datensatz einen Select nachschiessen, der die von der Db generierte ID abfragt, und den ins Dataset einpflegen.
    Gelöst ist das zB in meine DbExtensions :P

    Aber auch das kannst du dir selbstgebastelt antun: gugge Auslesen des neuen Wertes der Schlüsselspalte nach dem Erstellen eines neuen Datensatzes mit @@Identity