I am having a problem trying to save records in a parent / child data relation. I have to tables tblContacts & tblMember. There is a fk relation on the ContactID field. The tblContacts table is the master record. I am using a set up bound windows forms controls to do the data collection. The problem that I am having is in saving the child record. After the form is populated in both the fields and hitting the save button the items in the child record get deleted. It does add a row in the child record but only the ContactID (from the master table) and the key for the tblMember table.

I can see that since the new master record incites the addition of a new row, the data is abandoned. Once there is a save done to the master / child record I can go back and modify the fields and it saves it successfully. I know I must be missing something small. I am not sure how to work around this so that the controls are read into memory and then completed in the new row. I have an example of my code:

Private Sub TblContactsBindingNavigatorSaveItem_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TblContactsBindingNavigatorSaveItem.Click

        Dim newMemberRow As DataRow 'To create a new row in the tblMember table
        Dim contactID As Integer 'To hold the contactID to insert in the new member ContactID field
        Dim rowsaffected As Integer 'To indicate the number of rows affected by update
        Dim contactIndex As Integer


        Me.Validate()
        Me.TblContactsBindingSource.EndEdit()
        Me.TblContactsTableAdapter.Update(Ds.tblContacts)

        ' Me.TblContactsBindingSource.MoveLast()


        contactIndex = Me.TblContactsBindingSource.Position()



        MessageBox.Show("The contact Index is " & contactIndex)

        contactID = Me.Ds.Tables("tblContacts").Rows(contactIndex).Item("ContactID")

        Me.TblContactsBindingSource.ResetBindings(True)

        If (Me.TblMemberBindingSource.Find("ContactID", contactID.ToString()) < 0) Then



            MessageBox.Show("Current Position in table " & TblMemberBindingSource.Position().ToString())


            MessageBox.Show("The ContactID is " & contactID.ToString())




            '  newMemberRow = Ds.Tables("tblMember").NewRow()
            '  newMemberRow.Item("ContactID") = contactID
            '  newMemberRow.Item("Status") = StatusTextBox.Text
            '  newMemberRow.Item("MemberNotes") = MemberNotesTextBox.Text
            

            Try
                Ds.Tables("tblMember").Rows.Add(newMemberRow)
                Me.Validate()
                
                Me.TblMemberBindingSource.EndEdit()
                Me.TblMemberTableAdapter.Update(Ds.tblMember)


            Catch ex As Exception

                MessageBox.Show(ex.Message)

            End Try

        ElseIf (Me.TblMemberBindingSource.Find("ContactID", contactID.ToString()) >= 0) Then

            TblMemberBindingSource.MoveFirst()

            Try
                Me.TblMemberBindingSource.EndEdit()

            Catch ex As Exception

                MessageBox.Show(ex.Message)

            End Try

        End If

        'Me.TableAdapterManager.UpdateAll(Me.Ds)

    End Sub

Dani AI

Generated

— common symptom: the child row never has its bound values committed before the master insert/refresh, so the DB insert ends up carrying only the FK and generated key. The posted snippet shows three likely contributors: the child DataRow was never instantiated (the newMemberRow creation is commented out), ResetBindings(True) is called mid-flow (which can abort in-progress edits), and the identity propagation from the master insert may not be reaching the in-memory master row before the child is saved.

Recommended sequence (keep control edits pushed into the DataRow, get the real ContactID, then create/save the child row):

  • Commit control edits and end edits on binding sources so bound controls write into their DataRows.
  • Ensure the master insert returns the DB-generated ContactID to the DataSet (TableAdapter configured to refresh the inserted row).
  • Create the child row through the child BindingSource (AddNew) or NewRow, set its ContactID from the already-saved master DataRow, EndEdit on the child, then update the child table.

A compact VB flow (different approach than the original snippet):

' force controls into their data rows
Form.ValidateChildren()
Dim masterView = CType(TblContactsBindingSource.Current, DataRowView)
Dim masterID As Integer = CInt(masterView("ContactID"))

' create child via the child binding source so bound controls populate it
Dim childView = CType(TblMemberBindingSource.AddNew(), DataRowView)
childView("ContactID") = masterID
TblMemberBindingSource.EndEdit()
TblMemberTableAdapter.Update(Ds.tblMember)

Troubleshooting checks: remove or postpone ResetBindings(True) until after updates; verify Ds.GetChanges() to see RowState and column values before any Update call; confirm the master TableAdapter's INSERT returns the identity (SELECT SCOPE_IDENTITY() or equivalent) and that UpdatedRowSource is set so the DataRow gets refreshed; watch SQL traffic (SQL Profiler) to verify parameter values actually sent. 's redirect to the other thread is relevant — that discussion contains alternate patterns (TableAdapterManager.UpdateAll, or explicit identity-refresh) that often solve this exact lifecycle issue.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.