MS Access自动编号字段和VB.net

时间:2016-11-13 19:50:48

标签: sql database vb.net ms-access-2010

我刚开始用vb.net自学数据库访问,我一直在使用this as a reference。我的MS Access数据库比我设置关系数据库时引用的示例稍微复杂一点。我有两张桌子;球员和村庄。每个玩家可以再拥有一个村庄(1对多关系),这种关系在玩家ID之间绑定,玩家ID是玩家表中的唯一键,在村庄表中用于定义村庄的所有者。以下是我向数据库中添加新玩家的方法;

    Public Sub NewPlayer(ByVal playerName As String)
    Dim playerID As Integer = getLastIdent("Players") + 1
    Dim tmpnum As Integer = playerID

    Dim dsNewRow As DataRow
    Dim Sql As String

    Sql = "SELECT * FROM Players"

    da = New OleDb.OleDbDataAdapter(Sql, con)
    da.Fill(ds, "Players")

    Dim cb As New OleDb.OleDbCommandBuilder(da)

    dsNewRow = ds.Tables("Players").NewRow()

    dsNewRow.Item("ID") = playerID
    dsNewRow.Item("NameP") = playerName
    dsNewRow.Item("Coins") = 0


    ds.Tables("Players").Rows.Add(dsNewRow)

    da.Update(ds, "Players")

    Call NewVillage(playerName, playerID)
End Sub

getLastIdent子例程是我尝试查找玩家ID字段中使用的最后一个值;

    Public Function getLastIdent(ByVal tblname As String)
    Dim sql As String = "SELECT @@IDENTITY FROM " & tblname
    Dim cmd As New OleDb.OleDbCommand(Sql, con)
    Return cmd.ExecuteScalar()
End Function

但这根本不起作用(无论如何都返回0)。玩家实际上可以毫无障碍地创建(错误的ID号似乎在数据库正确递增自动编号的某个时刻自行修复。但是为了给新玩家分配一个村庄我运行NewVillage;

Public Sub NewVillage(ByVal playerName As String, ByVal playerID As Integer)
    Dim numVils As Integer = getVilCount()
           Dim xpos As Integer
    Dim ypos As Integer
    xpos = CInt(Rnd()*50)
    ypos = CInt(Rnd()*50)


    Dim dsNewRow As DataRow
    Dim Sql As String

    Sql = "SELECT * FROM Villages"

    da = New OleDb.OleDbDataAdapter(Sql, con)
    da.Fill(ds, "Villages")

    Dim cb As New OleDb.OleDbCommandBuilder(da)

    dsNewRow = ds.Tables("Villages").NewRow()

    dsNewRow.Item("ID") = numVils + 1
    dsNewRow.Item("NameV") = playerName & "'s Village"
    dsNewRow.Item("Xpos") = xpos
    dsNewRow.Item("Ypos") = xpos
    dsNewRow.Item("Owner") = playerID


    ds.Tables("Villages").Rows.Add(dsNewRow)

    da.Update(ds, "Villages")

End Sub

这就是整个事情崩溃的地方。传递给子程序的playerID不是与我刚刚创建的玩家相关联的正确值(面对那个名称没有任何玩家,因为它总是尝试playerID = 1并且AutoNumber开始高于到期时间删除失败的行)。

那么如何才能从玩家表中获取ID的真实价值呢?是否有一些我可以强制要求AutoNumber更新的调用,然后我可以重新检查它?

1 个答案:

答案 0 :(得分:1)

我过去所做的是挂钩OleDbDataAdapter的RowUpdated事件,并在该钩子中执行身份检索命令。

首先,定义将用于在模块级别执行identity子句的命令,并添加一个方法来实例化它:

Private cmdGetIdentity As OleDb.OleDbCommand

Private Sub CreateIdentityCommand(con As OleDbConnection, tblName As String)

    Dim sql As String = "SELECT @@IDENTITY FROM " & tblName
    cmdGetIdentity = New OleDb.OleDbCommand(sql, con)

End Sub

接下来,创建将用于检索标识的事件处理程序(因为每个表都包含一个ID列,此代码可用于两个表):

Private Sub RowUpdated(ByVal sender As Object, ByVal e As OleDbRowUpdatedEventArgs)

    If e.Status = UpdateStatus.Continue AndAlso e.StatementType = StatementType.Insert Then
        ' Execute the command and move it into the row
        e.Row("ID") = Int32.Parse(cmdGetIdentity.ExecuteScalar().ToString())
        ' Ensure the row's changes are accepted
        e.Row.AcceptChanges()
    End If

End Sub

最后,修改现有方法以实例化identity命令,挂钩新事件,并删除尝试设置ID的现有代码。例如,在NewVillage中,更改:

    da = New OleDb.OleDbDataAdapter(Sql, con)

    da = New OleDb.OleDbDataAdapter(Sql, con)
    CreateIdentityCommand(con, "Villages")
    AddHandler da.RowUpdated, AddressOf RowUpdated

然后删除这些行:

     Dim numVils As Integer = getVilCount()

     dsNewRow.Item("ID") = numVils + 1