【问题标题】:Adding data to an Access table将数据添加到 Access 表
【发布时间】:2016-08-25 20:22:41
【问题描述】:

我的应用程序通过 comport 读取比例并执行一些逻辑。然后我希望它向 Access 数据库输出 6 个读数:

  • 日期/时间时间两次
  • 状态
  • 层数
  • 零件数
  • 称重

我从网上提取了这段代码,声明dbInsert.ExcuteNonQuery ()得到错误

条件表达式中的数据类型不匹配

代码:

Dim dbInsert As New OleDb.OleDbCommand
Dim dbConnect As New OleDb.OleDbConnection
Dim Line As String = Environment.NewLine
Dim Status As String
Dim Stamp As Date
Dim pc As Double
Dim lc As Double

Sub AddToDb ()
    Try
        dbConnect.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source = C:\Users\aholiday\Desktop\Test\Test_be.accdb"
        dbConnect.Open()
        dbInsert.Parameters.Add(dbInsert.CreateParameter).ParameterName = "Date_Stamp"
        dbInsert.Parameters.Item("Date_Stamp").Value = Stamp
        dbInsert.Parameters.Add(dbInsert.CreateParameter).ParameterName = "Time_Stamp"
        dbInsert.Parameters.Item("Time_Stamp").Value = Stamp
        dbInsert.Parameters.Add(dbInsert.CreateParameter).ParameterName = "Status"
        dbInsert.Parameters.Item("Status").Value = Status
        dbInsert.Parameters.Add(dbInsert.CreateParameter).ParameterName = "Layer_Count"
        dbInsert.Parameters.Item("Layer_Count").Value = lc
        dbInsert.Parameters.Add(dbInsert.CreateParameter).ParameterName = "Part_Count"
        dbInsert.Parameters.Item("Part_Count").Value = pc
        dbInsert.Parameters.Add(dbInsert.CreateParameter).ParameterName = "Weight"
        dbInsert.Parameters.Item("Weight").Value = WeightAConvert
        Try
            dbInsert.CommandText = "INSERT INTO Log VALUES (Stamp,Stamp, Status, lc, pc, WeightAConvert);"
            dbInsert.CommandType = CommandType.Text
            dbInsert.Connection = dbConnect
            dbInsert.ExecuteNonQuery()
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    Catch ex As Exception
        MessageBox.Show(ex.Message)
        Me.Close()
    End Try
End Sub

更新代码:

Try

        Dim SQL = "INSERT INTO Scale_Log (Date_Stamp,Time_Stamp, Status, Layer_Count, Part_Count, Weight) VALUES (Stamp,Stamp,Status,lc,pc,WeightAConvert)"

        Using dbCon As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source = C:\Users\aholiday\Desktop\Test\Line_6&7_Weight_Log_be.accdb")

            Using cmd As New OleDbCommand(SQL, dbCon)
                cmd.Parameters.Add("Date_Stamp", OleDbType.Date).Value = Stamp
                cmd.Parameters.Add("Time_Stamp", OleDbType.Date).Value = Stamp
                cmd.Parameters.Add("Status", OleDbType.VarChar).Value = Status
                cmd.Parameters.Add("Lay_Count", OleDbType.Double).Value = lc
                cmd.Parameters.Add("Part_Count", OleDbType.Double).Value = pc
                cmd.Parameters.Add("Weight", OleDbType.Double).Value = WeightAConvert
                dbCon.Open()
                Dim rows = cmd.ExecuteNonQuery()
                cmd.Dispose()
            End Using

            dbCon.Close()

            dbCon.Dispose()

        End Using
    Catch ex As Exception

        MessageBox.Show(ex.Message)

        Exit Sub
    End Try

【问题讨论】:

  • 您的 SQL 没有将值映射到列。如果数据库不按该顺序返回列,您将尝试将一些东西放入 wring 列中。 SQL 应该包含参数,而不是与其他数据库提供程序有关的变量("Date_Stamp" 而不是Stamp)。另外,打开 Option Strict - layerCount 和其他一些没有在我们可以看到的代码中声明
  • @Plutonix 我并没有真正理解你的意思,你在说改变 dbInsert.Parameters.Add(dbInsert.CreateParameter).ParameterName = "Date_Stamp" dbInsert.Parameters.Item("Date_Stamp").Value = Stamp 中的内容,这是 2000 行代码的一个片段,LayerCount 在其他地方声明

标签: .net vb.net ms-access oledb


【解决方案1】:

您没有在 SQL 中指定列,因此您无法控制将哪个变量映射到哪个数据库列。当您碰巧以正确的顺序添加参数时,它将起作用。不要碰运气:当它出错时,您可能会收到数据不匹配错误。

此外,您似乎正在使用全局 DBConnectionDBCommand 对象。 不要这样做,因为它会导致各种问题:

  • 从根本上说,DBCommand 对象是特定于查询的,因此它没有重用价值
  • 下次您使用该命令对象时,它已经定义了 6 个参数。这可能会导致下一次的参数过多。
  • 由于 DBCommand 对象需要对连接的引用(您的代码中的 dbInsert.Connection = dbConnect),如果不释放它,您也不会关闭或释放该连接。

当然,如果传递的数据类型与db列类型不匹配,也会导致数据类型不匹配。你想要这样的东西:

Dim SQL = "INSERT INTO [Log] (colA, colB, colC...) VALUES (?,?,?,?,?,?)"

' dont use global provider objects
Using dbCon As New OleDbConnection(ACEConnStr)   ' use YOUR connection string
    Using cmd As New OleDbCommand(SQL, dbCon)

        ' do these in the exact same order as the cols are listed in the SQL
        cmd.Parameters.Add("?", OleDbType.Date).Value = Stamp       ' colA
        cmd.Parameters.Add("?", OleDbType.Date).Value = Stamp       ' colB
        cmd.Parameters.Add("?", OleDbType.VarChar).Value = Status
        '...
        cmd.Parameters.Add("?", OleDbType.Double).Value = ItemWeight 'colF
        dbCon.Open()
        Dim rows = cmd.ExecuteNonQuery()
    End Using
End Using
  • 首先,Log 可能是 Access-SQL 中的保留字,所以我对名称进行了转义1。列及其顺序在 SQL 语句中指定。
  • SQL 中的?,?,?,? 列表是占位符。您也可以使用 @p1, @p2,@p3... 甚至名称,但 OleDB 将仅按位置使用它们(请继续阅读)。
  • 每个cmd.Parameters.Add("?",... 语句都提供每个数据。这就是您的代码为 SQL 中的每个参数映射/提供值的方式。
  • DateTime 列将同时包含日期和时间。我不知道你为什么要分开存放它们。
  • 对于其他提供者,它们会根据参数名称 (cmd.Parameters.Add("@firstName", ...).Value = myFirstNameVar) 映射值。 OleDB 不使用这样的命名参数,因此您必须按照列名出现在 SQL 中的完全相同的顺序提供参数值。
  • Using 阻止创建目标对象以供您使用,然后在最后关闭并丢弃它们。您的连接字符串可以是全局变量。

最后,考虑传递它们,而不是像 layercount 这样的全局变量:

Sub AddToDb(foo As String, Stamp As DateTime, lc As Double....)

1.我不确定在这种情况下是否真的如此,but it is on a list

另请参阅:Using Statement 在 MSDN 上

【讨论】:

    猜你喜欢
    • 2011-01-23
    • 1970-01-01
    • 2016-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-31
    • 1970-01-01
    相关资源
    最近更新 更多