简体   繁体   中英

SQLCommandBuilder - UPDATE from DataTable only “Appends” Database Table

I am trying to UPDATE database table rows using SQLCommandBuilder with datatable rows using the following test code. One table with a primary key column and one datatable to keep it simple.

Using the following code, the dbo.Dogs2 table is "appended" with the datatable rows - therefore doubling the number of rows rather than just updating the changed row(s)

If I add the code table.AcceptChanges() just before the Dim builder As New SqlCommandBuilder(adapter) , the database table dbo.Dogs2 remains unchanged.

If I add the code table.AcceptChanges() just before the adapter.Update(table) , the database table dbo.Dogs2 remains unchanged.

Public Class Form1

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

        ' dbo.Dogs2 database table columns are exactly like datatable columns with exception of dog names
         ' only UPDATING the "Name" field (no Inserts or deletes)
         ' orginal dog names "Name" in Dogs2.dbo are Sharpy, Bully, Shep, Charlie, and Yorky
         ' new dog names "Name" in Dogs2.dbo are June, Tucker, Maggie, Charles, and Candy
         ' Dex_Row_Id is the primary key with Identity Increment set to 1

        ' Create a DataTable with five columns.
         '
         Dim table As New DataTable()
         table.Columns.Add("Weight", GetType(Integer))
         table.Columns.Add("Name", GetType(String))
         table.Columns.Add("Breed", GetType(String))
         table.Columns.Add("Size", GetType(Char))
         table.Columns.Add("Date", GetType(DateTime))
         table.Columns.Add("Dex_Row_Id", GetType(Integer))
         '
         ' Add data to the DataTable
         '
         AddDogRow(table, 57, "June", "Shar Pei")
         AddDogRow(table, 130, "Tucker", "Bullmastiff")
         AddDogRow(table, 92, "Maggie", "Anatolian Shepherd Dog")
         AddDogRow(table, 25, "Charles", "Cavalier King Charles Spaniel")
         AddDogRow(table, 7, "Candy", "Yorkshire Terrier")

        ShowResult(table)    'displays datatable correctly    (this is a DevExpress.com Reference/Extension)
         '
         ' Create new SqlConnection, SqlDataAdapter, and builder.
         '
         Dim cnString As String = "<<<SQLConnectionString>>>"
         '
         Using cnSQL1 As New SqlConnection
             cnSQL1.ConnectionString = cnString

            Using adapter = New SqlDataAdapter("SELECT * FROM Dogs2", cnSQL1)

                ShowResult(table)  'displays datatable

                Dim builder As New SqlCommandBuilder(adapter)
                 adapter.UpdateCommand = builder.GetUpdateCommand()
                 builder.RefreshSchema()

                Using New SqlCommandBuilder(adapter)
                     '
                     ' Fill the DataAdapter with the values in the DataTable.
                     '
                     adapter.Fill(table)  

                    ShowResult(table)  'displays datatable + original table data

                    ' Open the connection to the SQL database.
                     '
                     cnSQL1.Open()

                    ' Update the SQL database table with the values.
                     '
                     adapter.Update(table)

                    ' dbo.Dogs2 now has 10 rows  (the 5 rows from the dataset + the original 5 rows)

                End Using

            End Using

        End Using

    End Sub

You are using incorrectly the adapter. You should first load the rows from the database, then update the retrieved rows and finally call the update.

 ' REMOVE THE CODE BEFORE THIS '
 ' Create new SqlConnection, SqlDataAdapter, and builder.'

 Dim cnString As String = "<<<SQLConnectionString>>>"
 Dim table = New DataTable() ' Leave it emtpy and without schema'
 Using cnSQL1 As New SqlConnection
    cnSQL1.ConnectionString = cnString
    Using adapter = New SqlDataAdapter("SELECT * FROM Dogs2", cnSQL1)
        Dim builder As New SqlCommandBuilder(adapter)
        adapter.UpdateCommand = builder.GetUpdateCommand()
        ' no need of this -> builder.RefreshSchema()'
        Using New SqlCommandBuilder(adapter)
            adapter.Fill(table)  
            ShowResult(table)  'displays original table data'

            ' no need of this -> cnSQL1.Open()'
            ' NOW YOU COULD CHANGE THE ROWS, FOR EXAMPLE'
            table.Rows(0)("Weight") = 99

            ' Update the SQL database table with the values.'
            adapter.Update(table)
        End Using
    End Using
End Using

When you pass an existing table to the Fill method of the Adapter, the existing record are not removed and thus your table is filled with data from the database and from your manual creation of the table (Of course the Adapter build for you the table columns. Moreover, the rows added manually to your table are marked with the DataRowState.Added while the row modified by your code will be marked with the DataRowState.Changed . This state helps the Update command to decide which action to perform on every row present in the table (Of course the rows that are not changed maintain the initial DataRowState.Unchanged

Finally, calling AcceptChanges doesn't mean that the rows will be updated on the database table. Only the DataRowState flag is reset to the DataRowState.Unchanged

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM