Pergunta

I have a form with a DataGridView bound to a BindingSource object which is connected to an Access Database which uses Autonumber as the ID field.

When records are edited, deleted, or created, I run the DataAdapter's update method which is working great. But new records do not show their ID and attempting to delete a new record results in a DBConCurrencyException.

Is there some way for me to tell the BindingSource, Databable, or Dataset to refresh/reload the record? Of what is the best way to show the Autonumber ID for the new record?

(Warning, I know this is not well written, well abstracted code.)

Private conString As String = "Provider=Microsoft.ACE.OLEDB.12.0; " +
                            "Data Source=C:\data.accdb"
Private conn As OleDbConnection
Private WithEvents da As OleDbDataAdapter
Private ds As DataSet
Private builder As OleDbCommandBuilder
Private WithEvents bs As BindingSource

Private Sub AccessDataGridView_Load(sender As Object, e As EventArgs) Handles Me.Load
    dgv1.AutoGenerateColumns = True
    Call GetData("SELECT * FROM lots")
    dgv1.DataSource = bs
    dgv1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells)
End Sub

Private Function GetData(sSQL As String)
    If conn Is Nothing Then
        conn = New OleDbConnection
        conn.ConnectionString = conString
        conn.Open()
    End If
    da = New OleDbDataAdapter(sSQL, conn)
    builder = New OleDbCommandBuilder(da)
    ds = New DataSet
    da.Fill(ds)
    bs = New BindingSource
    bs.DataSource = ds.Tables(0)
End Function

Private Sub bs_CurrentItemChanged(sender As Object, e As EventArgs) Handles bs.CurrentItemChanged
    If ds.HasChanges() = True Then
        da.Update(CType(bs.DataSource, DataTable))
    End If
End Sub

Private Sub bs_ListChanged(sender As Object, e As System.ComponentModel.ListChangedEventArgs) Handles bs.ListChanged
    If ds.HasChanges() = True Then
        da.Update(CType(bs.DataSource, DataTable))
    End If
End Sub

Private Sub da_RowUpdated(sender As Object, e As OleDbRowUpdatedEventArgs) Handles da.RowUpdated
    If e.Status = UpdateStatus.Continue _
          AndAlso e.StatementType = StatementType.Insert Then
        Dim cmdGetIdentity As OleDbCommand
        cmdGetIdentity = New OleDbCommand()
        cmdGetIdentity.CommandText = "SELECT @@IDENTITY"
        cmdGetIdentity.Connection = conn
        e.Row("lotid") = Int32.Parse(cmdGetIdentity.ExecuteScalar().ToString())
        e.Row.AcceptChanges()
        'This appears to work with no problem, but the DataGridView
        'still doesn't show the new ID
        'EDIT
        dgv1.Refresh() 'This fixed the problem mentioned directly above
    End If
End Sub
Foi útil?

Solução

The way that auto-generated IDs are propagated back into your DataTable when using SqlClient is by including a SELECT statement in the CommandText of your InsertCommand. The Jet and ACE OLE DB providers do not support multiple statements per command so that's not an option. I've written some example code for Access specifically on another site but it's down at the moment so I can't give you the link. Here's another example:

http://support.microsoft.com/kb/816112/en-gb

That code is C# but the principle is exactly the same: handle the RowUpdated event of your data adapter, get the ID from the database and update the DataRow.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top