I have a windows form that references two tables with a foreign key constraint issue. This form uses detail views for both tables. The tables are tblContact and tblMembers. The relation is based on the ContactID that is in both tables. The parent is in the tblContact table.

I am using the binding source to do record navigation. Overall this is working well. When I have data in both tables it performs navigation accurately. Modification works if there is existing data in both tables that meet the relationship. The problem that I have is when I try to find if there is an existing record in the tblMembers table. I can't use find. I know that it has to do with accessing the detail table correctly. I am pretty sure that this is done via getting the properties of the table and accessing the PropertyDescriptorCollection.

Either way I am looking to save the data in the tables in a safe way. I am also concerned that I might have concurrency problems with the way that I am getting records.

Here is a code example that I am trying:

Imports System.ComponentModel

Public Class frmMember

    Private Sub TblContactsBindingNavigatorSaveItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
        Me.Validate()
        Me.TblContactsBindingSource.EndEdit()
        Me.TableAdapterManager.UpdateAll(Me.Ds)

    End Sub


    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")



        MessageBox.Show("The ContactID is " & contactID.ToString())
        newMemberRow = Ds.Tables("tblMember").NewRow()
        newMemberRow.Item("ContactID") = contactID
        newMemberRow.Item("Status") = StateTextBox.Text
        newMemberRow.Item("MemberNotes") = MemberNotesTextBox.Text

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

        Catch ex As Exception

            MessageBox.Show(ex.Message)

        End Try

        Me.TableAdapterManager.UpdateAll(Me.Ds)

    End Sub

    Private Sub frmMember_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'TODO: This line of code loads data into the 'Ds.tblMember' table. You can move, or remove it, as needed.
        Me.TblMemberTableAdapter.Fill(Me.Ds.tblMember)
        'TODO: This line of code loads data into the 'Ds.tblContacts' table. You can move, or remove it, as needed.
        Me.TblContactsTableAdapter.Fill(Me.Ds.tblContacts)

    End Sub

    Private Sub BindingNavigatorAddNewItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BindingNavigatorAddNewItem.Click

    End Sub

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

        Dim props As PropertyDescriptorCollection = TblMemberBindingSource.CurrencyManager.GetItemProperties()

        If (TblMemberBindingSource.Find(props["ContactID"], "5") >= 0) Then

            MessageBox.Show("There were records found")

        End If


    End Sub
End Class

Dani AI

Generated

Short summary and practical fixes (expanded from and )

The symptom is expected: BindingSource.Find forwards the search to whatever the underlying list implements (IBindingList.Find), so Find will only work when that inner list actually supports searching. When the list is a DataView the search goes to DataView.Find (which requires a sort key), and the fastest lookup by key is DataTable.Rows.Find — but that requires a PrimaryKey on the DataTable. (learn.microsoft.com)

Practical options (pick one that fits your design):

  • Prefer primary-key lookup: set the PrimaryKey for tblMember and use DataTable.Rows.Find(contactID) to get the child DataRow directly (very fast and stable across sorts/filters). This avoids relying on BindingSource.Position mapping to DataRow indexes.

  • Use a sorted DataView when you need index-based searching: set DefaultView.Sort = "ContactID" and call DefaultView.Find(contactID). DataView.Find only works when the view has a sort key. (learn.microsoft.com)

  • For master/detail binding, keep a child BindingSource that uses the parent BindingSource as DataSource and DataMember = "parent.child"; then the child BindingSource.Count (or Current) tells you whether a child exists for the current parent. If you ever mutate the DataTable programmatically, call ResetBindings so controls reread the list (this is what saw — ResetBindings forces a control refresh). (learn.microsoft.com)

Concurrency and safety notes

Do not rely on Position to identify rows for persistence; use the ContactID primary key. Use optimistic concurrency (rowversion/timestamp or original-value checks generated by TableAdapters) and handle update conflicts from TableAdapter/DbAdapter.Update with a try/catch and a refresh/reload strategy. That pattern is the standard ADO.NET approach to avoid lost updates. (learn.microsoft.com)

Example snippets above use safe lookups; insert/update sequences should still call your TableAdapter.Update (and avoid calling AcceptChanges before Update). 's local-settings tip is useful for UI persistence but does not replace proper record lookup/update logic for a relational dataset.

Recommended Answers

All 2 Replies

hope this might help i save contents from a listbox to internal settings file.

you could add this to the above code to save it safely

If ListBox8.Items.Count > 0 Then
            My.Settings.Names.Clear()
            For Each LI As String In ListBox8.Items
                My.Settings.Names.Add(LI)
            Next
        End If

Ok. I found out that to get the insert done this way you have to reset the bindingsource. As in

Me.TblContactsBindingSource.ResetBindings(True)
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.