forgottenrealm
Goto Top

Anbindung von Textboxen an Datenbank

Hallo

Ich stehe vor einem, wahrscheinlich sehr schnell zu lösendem, Problem mit ein paar TextBoxen, einer Combobox und dem CommandBuilder.

Mein Code schaut zur Zeit so aus;

Option Explicit On

'Systemobjekte  
Imports System.Data

'MS Access  
Imports System.Data.OleDb

Public Class frm_Einstellungen

    Private Private_tbl_EMailKonten_BindingSource As New BindingSource()
    Private Private_tbl_EMailKonten_Adapter As New OleDbDataAdapter()
    Private Private_tbl_EMailKonten_CommandBuilder As New OleDbCommandBuilder()

    Private Private_tbl_DMC_data_CurrentID As Long

    Private Private_ArrayDBFelder() As Control = Nothing

    Private Sub frm_Einstellungen_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        Try
            frm_Start.Hide()

            'Ersten Datensatz in Tabelle schreiben  
            If DBExcecute("SELECT COUNT(*) AS RecordCounts FROM " & Const_tbl_EMailKonten, "RecordCounts") = 0 Then  
                Call DBExcecute("INSERT INTO " & Const_tbl_EMailKonten & " (EMailKonto) VALUES (" & ConstSQLEscape & Nothing & ConstSQLEscape & ")")  
            End If

            'Datenbank anbinden  
            Dim TV_SQLString As String = "SELECT * FROM " & Const_tbl_EMailKonten  
            Private_tbl_EMailKonten_Adapter = New OleDbDataAdapter(TV_SQLString, Public_MSAccConnectString)
            Dim commandBuilder As New OleDbCommandBuilder(Private_tbl_EMailKonten_Adapter)

            'Databinding  
            Private_tbl_EMailKonten_BindingSource.DataSource = CreateDataTable("SELECT * FROM " & Const_tbl_EMailKonten, "DS_EMailKonten")  

            With Private_tbl_EMailKonten_BindingSource
                cb_EMailKonto.DataSource = .DataSource
                cb_EMailKonto.DisplayMember = "EMailKonto"  
                cb_EMailKonto.ValueMember = "MyID"  

                Private_tbl_DMC_data_CurrentID = .DataSource.Rows(0)("MyID")  
                tb_Benutzername.DataBindings.Add("Text", .DataSource, "Benutzername")  
                tb_MailDomain.DataBindings.Add("Text", .DataSource, "MailDomain")  
                tb_Passwort.DataBindings.Add("Text", .DataSource, "Passwort")  
                tb_POPServer.DataBindings.Add("Text", .DataSource, "POPServer")  
                tb_POPPort.DataBindings.Add("Text", .DataSource, "POPPort")  
                tb_SMTPServer.DataBindings.Add("Text", .DataSource, "SMTPServer")  
                tb_SMTPPort.DataBindings.Add("Text", .DataSource, "SMTPPort")  
            End With

            'Passwort Felder maskieren  
            tb_Passwort.UseSystemPasswordChar = True

            'Felder einfärben  
            Private_ArrayDBFelder = {tb_Benutzername, tb_MailDomain, _
                                        tb_Passwort, tb_Benutzername, _
                                        tb_POPServer, tb_POPPort, _
                                        tb_SMTPServer, tb_SMTPPort}

            For Each CurrentFeld In Private_ArrayDBFelder
                If TypeOf CurrentFeld Is TextBox Then
                    If Not CurrentFeld.Text = Nothing Then 'Mit Inhalt  
                        CurrentFeld.BackColor = Color.LightGreen
                    Else 'Ohne Inhalt  
                        CurrentFeld.BackColor = Color.LightSalmon
                    End If
                End If
            Next CurrentFeld

            Exit Sub

        Catch ex As Exception
            MsgBox(ex.Message, vbOKOnly + vbCritical)

        End Try

    End Sub

End Class

Ich bin mir nicht sicher, ob es so richtig ist, aber das Binding an die Textfelder und die Combobox funktioniert. Wenn ich den Datensatz in der Combobox wechsle dann werden die Änderungen auch wie gewünscht übernommen, allerdings wird nichts gespeichert wenn ich in dem Datensatz bleibe und das Speichern über einen Button mit dem Dataadapter.update ausführe.

    Private Sub btn_Speichern_Click(sender As Object, e As EventArgs) Handles btn_Speichern.Click

        Dim commandBuilder = New OleDbCommandBuilder(Private_tbl_EMailKonten_Adapter)

        Private_tbl_EMailKonten_Adapter.Update(Private_tbl_EMailKonten_DataSet, "DS_EMailKonten") 'Datenherkunft aus DataSet  

        Private_tbl_EMailKonten_Adapter.Update(CType(Private_tbl_EMailKonten_BindingSource.DataSource, DataTable)) 'Datenherkunft aus BindingSource  

        MsgBox(commandBuilder.GetUpdateCommand.CommandText)

    End Sub

Der Commandbuilder gibt mir als Updatetext nur ? als Wert für die Felder zurück.

Ich probiere seit fast 30 Stunden jetzt immer wieder hin und her, komme aber nicht weiter leider. Ich hoffe, ihr könnt mir helfen.

Freundliche Grüße!

Content-ID: 242047

Url: https://administrator.de/contentid/242047

Ausgedruckt am: 26.11.2024 um 07:11 Uhr

colinardo
colinardo 27.06.2014 aktualisiert um 11:20:12 Uhr
Goto Top
Hallo ForgottenRealm,
du benötigst noch die eigentliche Update-Routine für den OleDbDataAdapter, sonst weiß dieser ja nicht wie er die Werte in der DB updaten soll. Diese kannst du mit einem OleDbCommandBuilder automatisch generieren lassen:

Beispiel:
Dim da As New OleDb.OleDbDataAdapter("SQL String")  
Dim builder As OleDb.OleDbCommandBuilder = New OleDb.OleDbCommandBuilder(da)
da.UpdateCommand = builder.GetUpdateCommand()
Danach kannst du mit der Update() Methode des DataAdapter den Datensatz in der DB aktualisieren.

Noch ein Hinweis: Du benötigst für jeden Vorgang den du in der Datenbank machen möchtest (Update,Insert,Delete) jeweils solch eine Routine für den DataAdapter. Diese kannst du ebenfalls vom OleDbCommandBuilder automatisch erstellen lassen, siehe dazu die oben verlinkte Referenzseite.

Grüße Uwe
ForgottenRealm
ForgottenRealm 27.06.2014 um 12:28:34 Uhr
Goto Top
Hallo Uwe,

Ich dachte mir schon, dass ich irgend etwas vergessen habe ...

Allerdings steh ich grad echt auf dem Schlauch, wo muss ich in meinem Code damit hin?

Mein Code sieht grad so aus;

Option Explicit On

'Systemobjekte  
Imports System.Data

'MS Access  
Imports System.Data.OleDb

Public Class frm_Einstellungen

    Private Private_tbl_EMailKonten_BindingSource As New BindingSource()
    Private Private_tbl_EMailKonten_Adapter As New OleDbDataAdapter()
    Private Private_tbl_EMailKonten_CommandBuilder As New OleDbCommandBuilder()

    Private Private_tbl_EMailKonten_DataSet As New DataSet

    Private Private_tbl_DMC_data_CurrentID As Long

    Private Private_ArrayDBFelder() As Control = Nothing

    Private Sub frm_Einstellungen_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        Try
            frm_Start.Hide()

            'Ersten Datensatz in Tabelle schreiben  
            If DBExcecute("SELECT COUNT(*) AS RecordCounts FROM " & Const_tbl_EMailKonten, "RecordCounts") = 0 Then  
                Call DBExcecute("INSERT INTO " & Const_tbl_EMailKonten & " (EMailKonto) VALUES (" & ConstSQLEscape & Nothing & ConstSQLEscape & ")")  
            End If

            'Datenbank anbinden  
            Dim TV_SQLString As String = "SELECT * FROM " & Const_tbl_EMailKonten  

			
            'Databinding  
            Private_tbl_EMailKonten_BindingSource.DataSource = CreateDataTable(TV_SQLString, "DS_EMailKonten")  
			
            'Command Builder  
            Private_tbl_EMailKonten_Adapter = New OleDbDataAdapter(TV_SQLString, Public_MSAccConnectString)
            Private_tbl_EMailKonten_Adapter.Fill(Private_tbl_EMailKonten_DataSet, "DS_EMailKonten")  


            '################## Hier ist der neue teil  
            Private_tbl_EMailKonten_CommandBuilder = New OleDbCommandBuilder(Private_tbl_EMailKonten_Adapter
            '################## Hier ist der neue teil  

            With Private_tbl_EMailKonten_BindingSource
                cb_EMailKonto.DataSource = .DataSource
                cb_EMailKonto.DisplayMember = "EMailKonto"  
                cb_EMailKonto.ValueMember = "MyID"  

                Private_tbl_DMC_data_CurrentID = .DataSource.Rows(0)("MyID")  
                tb_Benutzername.DataBindings.Add("Text", .DataSource, "Benutzername")  
                tb_MailDomain.DataBindings.Add("Text", .DataSource, "MailDomain")  
                tb_Passwort.DataBindings.Add("Text", .DataSource, "Passwort")  
                tb_POPServer.DataBindings.Add("Text", .DataSource, "POPServer")  
                tb_POPPort.DataBindings.Add("Text", .DataSource, "POPPort")  
                tb_SMTPServer.DataBindings.Add("Text", .DataSource, "SMTPServer")  
                tb_SMTPPort.DataBindings.Add("Text", .DataSource, "SMTPPort")  
            End With
			
			...

        Catch ex As Exception
            MsgBox(ex.Message, vbOKOnly + vbCritical)

        End Try

    End Sub

    Private Sub btn_Speichern_Click(sender As Object, e As EventArgs) Handles btn_Speichern.Click

        Private_tbl_EMailKonten_Adapter.UpdateCommand = Private_tbl_EMailKonten_CommandBuilder.GetUpdateCommand()

        Private_tbl_EMailKonten_Adapter.Update(CType(Private_tbl_EMailKonten_BindingSource.DataSource, DataTable)) 'Datenherkunft aus BindingSource  

    End Sub

End Class


Aus dem Link bin ich leider nicht schlauer geworden, da dort alles noch etwas anders aufgebaut ist. Könntest du mir evtl. den Code soweit zusammenschieben, dass es passen müsste?
colinardo
colinardo 27.06.2014 aktualisiert um 13:18:15 Uhr
Goto Top
also ein bisschen mitdenken erwarte ich hier eigentlich schon, hatte dir ja schon die Vorlage geliefert.

ab Zeile 39
Private_tbl_EMailKonten_Adapter = New OleDbDataAdapter(TV_SQLString, Public_MSAccConnectString) 
Private_tbl_EMailKonten_Adapter.Fill(Private_tbl_EMailKonten_DataSet, "DS_EMailKonten")  
Dim builder As OleDb.OleDbCommandBuilder = New OleDb.OleDbCommandBuilder(Private_tbl_EMailKonten_Adapter)
Private_tbl_EMailKonten_Adapter.UpdateCommand = builder.GetUpdateCommand()
und Zeile 73 wech ...

Grüße Uwe
ForgottenRealm
ForgottenRealm 27.06.2014 um 13:42:24 Uhr
Goto Top
So rum hatte ich es schon probiert, leider ebenfalls ohne Erfolg.

Die Daten sind nach dem Öffnen der Maske wieder so wie sie vorher waren, anscheinend wird nichts gespeichert.


Mit kommt das Verhalten sehr merkwürdig vor, da beim Wechseln des Datensatzes über die Combobox die Daten gespeichert werden, unabhängig davon ob ich irgendwo etwas speichere oder nicht. Ich werde gleich nochmal ein komplett neues Projekt anfangen und dort nur den Teil verwenden, der so funktionieren müsste, möglicherweise ist bei meinem Programm einfach zu viel durcheinander.

Vielleicht siehst du ja noch etwas, woran es liegen könnte bei dem bestehenden Code ...

Freundliche Grüße face-smile
ForgottenRealm
ForgottenRealm 30.06.2014 aktualisiert um 14:02:37 Uhr
Goto Top
Moinmoin

Ich habs heute früh noch mal probiert, in einem neuen Projekt und nur mit den Wichtigsten Sachen.

Option Explicit On

'Systemobjekte  
Imports System.Data

'MS Access  
Imports System.Data.OleDb

Public Class Form1

    Private Private_tbl_EMailKonten_DA As New OleDbDataAdapter()
    Private Private_tbl_EMailKonten_DS As New DataSet
    Private Private_tbl_EMailKonten_RS As String = "DS_EMailKonten"  

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        Dim SQLString As String = "SELECT * FROM tbl_EVA_EMailKonten"  
        Dim SQLConString As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & "C:\Test\EVADat_vbNet.mdb" & ";Jet OLEDB:Engine Type=5"  

        Private_tbl_EMailKonten_DA = New OleDbDataAdapter(SQLString, SQLConString)
        Private_tbl_EMailKonten_DA.Fill(Private_tbl_EMailKonten_DS, Private_tbl_EMailKonten_RS)

        Dim builder As OleDb.OleDbCommandBuilder = New OleDb.OleDbCommandBuilder(Private_tbl_EMailKonten_DA)
        Private_tbl_EMailKonten_DA.UpdateCommand = builder.GetUpdateCommand()

        Dim dt As DataTable = Private_tbl_EMailKonten_DS.Tables(Private_tbl_EMailKonten_RS)

        'Combobox binden  
        ComboBox1.DataSource = dt
        ComboBox1.DisplayMember = "Benutzername"  
        ComboBox1.ValueMember = "MyID"  

        'Textfelder binden  
        With Private_tbl_EMailKonten_DS
            TextBox1.DataBindings.Add("Text", .Tables(Private_tbl_EMailKonten_RS), "Benutzername")  
            TextBox2.DataBindings.Add("Text", .Tables(Private_tbl_EMailKonten_RS), "MailDomain")  
        End With

        ComboBox1.DisplayMember = "EMailKonto"  
        ComboBox1.ValueMember = "MyID"  

    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        Private_tbl_EMailKonten_DA.Update(Private_tbl_EMailKonten_DS, Private_tbl_EMailKonten_RS)

    End Sub

End Class

Die Änderungen werden gespeichert, sobald ich den Datensatz durchwechsle. Beim Klicken auf den Button1 passiert mit dem aktuell ausgewähltem Datensatz leider rein gar nichts.

Ich bin langsam echt ratlos, da ich den Fehler einfach nicht finde ... so schwer kann das doch nicht sein, oder stell ich mich echt so dämlich an?

Freundliche Grüße!
colinardo
Lösung colinardo 30.06.2014 aktualisiert um 15:28:33 Uhr
Goto Top
Ach stimmt da fehlt in diesem Fall vor dem Update noch ein EndEdit() der BindingSource und danach noch ein AcceptChanges() des DataSets.
http://stackoverflow.com/questions/260000/updating-a-database-from-data ...
ForgottenRealm
ForgottenRealm 30.06.2014 um 15:29:46 Uhr
Goto Top
Hallo Uwe und vielen Dank für die Hilfe, genau das war es face-smile

Hätte mir von VBA her eigentlich noch klar sein müssen, war mir aber nicht bekannt ob dies bei VB.net auch nötig war.
ForgottenRealm
ForgottenRealm 01.07.2014 um 12:47:54 Uhr
Goto Top
Moinmoin

Leider gibt es doch noch ein Problem, wenn ich vom ersten auf einen anderen Datensatz wechsle und diesen mit;

            Private_tbl_EMailKonten_BindingSource.EndEdit()
            Private_tbl_EMailKonten_Adapter.Update(CType(Private_tbl_EMailKonten_BindingSource.DataSource, DataTable))
            Private_tbl_EMailKonten_DataSet.AcceptChanges()

speichern möchte, werden keinerlei Änderungen gespeichert.

Änderungen im ersten Datensatz werden richtig gespeichert, nur bei allen anderen nicht. Diese kann ich nur speichern, wenn der Datensatz gewechselt wird.
Allerdings erhalte ich auch keine Fehlermeldung. Hast du eine Idee, wo der Fehler ist?

Freundliche Grüße