更新时(此集合中已存在名称为“@xxxxxxx”的参数。

On a update (There is already a parameter with the name '@xxxxxxx' in this collection.)

提问人:Paul 提问时间:7/31/2023 最后编辑:Paul 更新时间:8/1/2023 访问量:203

问:

我正在使用 VB.NET、Visual Studio 2022、Win 10、MySQLConnector.dll (2.2.6.0) 我正在尝试将MySQL集成到一个框架中,该框架是 ADO.net 的包装器。让我试着创建一些上下文。

该框架最初是作为 AccessDB 的包装器,然后添加了 SQL Server。接下来是SQLite、CSV、XLS、AS400等。有一系列 case 语句为连接构建连接字符串。 然后创建所需的“DbProviderFactories”。 然后构建一个 'DataTable'(dt) 'DbCommand'(cmd)->'ExecuteReader'(reader as cmd.ExecteReader) ->dt。加载(读取器)。

主代码

    Dim tmp As clsDataTable = DataAccessIris.GetDT2("select * from ONLINEINFOAUX", "tmp", "MYSqlConnector",,, eErrReturn.Exception)
    DispThis("Tmp: " & tmp.RowCount.ToString & NewLine)
    tmp.LocalWalkFindRow(New Dictionary(Of String, Object) From {{"common_item_number", 50}})
    tmp.Rows(tmp.LocalWalkFindRecordNum)("ONLINE_DESCRIPTION") = "test"
    tmp.UpdateData()

clsDataTable 基于 .NET DataTable '.LocalWalkFindRow' 是一个函数,用于遍历查找匹配项的行并设置属性“LocalWalkFindRecordNum”。

所有这些工作都已加载,并且表已加载。我可以添加和删除记录。我可以访问行和字段。我可以更新行/字段。如果我显示行/字段,我可以看到更改。但是当我尝试更新表格时,我得到了主题“错误,其中@xxxxx”是我尝试更改的字段的名称中所述的内容。

更新类似于...... 从通过_da as Common.DbDataAdapterDbProviderFactories._da.Update(dt)

这是更新功能。“DataAccessIris”类有一个打开语句。打开后,它将存储在类型(String、DbDataAdapter)的数据字典中。传递的变量创建一个键,因此,如果 DbDataAdapter 存在,则只返回它,否则将生成、存储它,然后返回它。

        Public Sub UpdateData(Optional pSource As String = Nothing, Optional pDBnum As String = Nothing, Optional pStnum As String = Nothing, Optional DoUpdateEvent As Boolean = False)
            If pSource Is Nothing Then pSource = Me._Source
            If pDBnum Is Nothing Then pDBnum = Me._dbName
            If pStnum Is Nothing Then pStnum = Me._stNum


            Using _da As Common.DbDataAdapter = DataAccessIris.DBAdapter(pSource, pDBnum, pStnum, Me.Parms)
                If TypeOf _da Is SqlDataAdapter Then
                    AddHandler CType(_da, SqlDataAdapter).RowUpdating, AddressOf DA_RowUpdating
                    If DoUpdateEvent Then AddHandler CType(_da, SqlDataAdapter).RowUpdated, AddressOf DA_RowUpdated
                    'ElseIf TypeOf _da Is SQLiteDataAdapter Then
                    '    AddHandler CType(_da, SQLiteDataAdapter).RowUpdating, AddressOf DA_RowUpdating
                    '    If DoUpdateEvent Then AddHandler CType(_da, SQLiteDataAdapter).RowUpdated, AddressOf DA_RowUpdated
                ElseIf TypeOf _da Is Data.Odbc.OdbcDataAdapter Then
                    AddHandler CType(_da, Odbc.OdbcDataAdapter).RowUpdating, AddressOf DA_RowUpdating
                    If DoUpdateEvent Then AddHandler CType(_da, Odbc.OdbcDataAdapter).RowUpdated, AddressOf DA_RowUpdated
                ElseIf TypeOf _da Is Data.OleDb.OleDbDataAdapter Then
                    AddHandler CType(_da, OleDb.OleDbDataAdapter).RowUpdating, AddressOf DA_RowUpdating
                    If DoUpdateEvent Then AddHandler CType(_da, OleDb.OleDbDataAdapter).RowUpdated, AddressOf DA_RowUpdated
                End If
                If DoUpdateEvent Then
                    _rowsToUpdate = 0
                    _rowsUpdated = 0
                    For xloop As Integer = 0 To Me.RowCount - 1
                        If Me.Rows(xloop).RowState <> DataRowState.Unchanged Then _rowsToUpdate += 1
                    Next
                End If
                Dim _trans As DbTransaction = Nothing
                If _da.ToString = "System.Data.SQLite.SQLiteDataAdapter" Then
                    _trans = CType(DataAccessIris.OpenDb(pDBnum, pStnum).BeginTransaction, DbTransaction)
                End If
                _da.Update(Me)
                If _trans IsNot Nothing Then
                    _trans.Commit()
                    _trans.Dispose()
                End If
                If Me.Parms IsNot Nothing Then
                    For x As Integer = 0 To Me.Parms.Count - 1
                        _da.SelectCommand.Parameters.Remove(Me.Parms(x))
                    Next
                End If
            End Using

            blnSkipRowChange = True
            Me.AcceptChanges()
            MyBase.AcceptChanges()
            blnSkipRowChange = False
            SetInit()
        End Sub

此 Pastebin 链接指向 https://pastebin.com/Mh1ESe0f 生成的更新查询

我可以提供更多细节,但我不想让这篇文章比我已经做的更令人困惑。:-)

只是让我知道什么可能有助于使它更清楚。

编辑 2023 年 7 月 31 日以清除正在构建参数的位置。此外,还添加了 System.Data 和 ADO.Net 标记以获取更多上下文。 DBAdapter 是 System.DataCommon.DbDataAdapter 的包装器。 这是代码...

       Public Shared Function DBAdapter(ByVal CommandText As String,
                      Optional ByVal DataBaseName As String = "",
                      Optional ByVal StoreNumber As String = "",
                      Optional ByVal Prams() As DbParameter = Nothing) As DbDataAdapter
        Dim da As DbDataAdapter = Nothing
        Try
            DataBaseName = DataBaseName.ToUpper
            Dim conName As String = DataBaseName & StoreNumber
            Dim cmd As DbCommand = Nothing
            If Prams Is Nothing Then
                cmd = DBCommand(CommandText, DataBaseName, StoreNumber)
            Else
                cmd = DBCommand(CommandText, Prams, DataBaseName, StoreNumber)
            End If

            'If DataBaseName.ToUpper.EndsWith(".SQLITE") Then
            '    da = New SQLiteDataAdapter
            'Else
            da = DbProviderFactories.GetFactory(dProviderTypes(conName)).CreateDataAdapter
            'End If

            da.SelectCommand = cmd
            da.MissingSchemaAction = MissingSchemaAction.AddWithKey
            Dim cmdBuild As DbCommandBuilder
            'If DataBaseName.ToUpper.EndsWith(".SQLITE") Then
            '    cmdBuild = New SQLiteCommandBuilder
            'Else
            cmdBuild = DbProviderFactories.GetFactory(dProviderTypes(conName)).CreateCommandBuilder
            'End If
            cmdBuild.DataAdapter = da
            Try
                da.InsertCommand = cmdBuild.GetInsertCommand(True)
                da.UpdateCommand = cmdBuild.GetUpdateCommand(True)
                da.DeleteCommand = cmdBuild.GetDeleteCommand(True)
            Catch
            End Try
            Return da
        Catch ex As Exception
            Throw New Exception(ex.Message & " Command Text='" & CommandText & "'", ex)
        Finally
            da = Nothing
        End Try
    End Function

上面 https://pastebin.com/Mh1ESe0f Pastebin 链接是 CommandBuilder.GetUpdateCommand(True) 所做的。

只是为了进行比较,这里是插入和删除。

CommandBuilder.GetInsertCommand(True) https://pastebin.com/pJUhYCiY

CommandBuilder.GetDeleteCommand(True) https://pastebin.com/Sg32Snmx

同样的包装器用于 SQLite 和 SQL Server。要么我正在与一个错误作斗争,这会让我感到惊讶,因为我希望有很多人使用 ADO.Net 和 MySQLConnector。一定有一些我没有预料到的细微差别。例如,为了让SQLite工作,我必须“启动”和“提交”事务。

vb.net ado.net mysql-connector system.data

评论

2赞 Michael Foster 7/31/2023
错误显然与参数有关,但我在此代码中没有看到参数处理。是我遗漏了什么,还是缺少代码?我的猜测是您正在尝试多次更新相同的参数。
0赞 Paul 8/1/2023
@MichaelFoster我没有定义参数,但我相信是数据库工厂来定义的。“InsertCommand”、“DeleteCommand”和“UpdateCommand”属性来自“CreateCommandBuilder”GetInsertCommand、GetUpdateCommand 和 GetDeleteCommand。我传递了一个属性,该属性作为 true 传递给函数。这是 System.Data.Common.DbCommandBuilder 的一部分。这适用于 SQLite 和 SQL Server。让我更清晰地编辑我的帖子。
1赞 Hursey 8/1/2023
对我来说,对上述评论感到愤怒。您可能需要开始调试已粘贴的更新 sql 代码。然后,一旦知道问题的根源,就制定纠正计划
0赞 Paul 8/1/2023
@Hursey 对我来说,很多 ADO.Net 都是“黑匣子”。在大多数情况下,如果我加载它并运行这个函数,它就会起作用。我知道如果我使用“ExecuteCmd”来执行带有参数的 SQL 语句,我会使用数据类型参数来传递它们。我没有连接的点是 ADO.Net 更新的方式。这确实给了我一个不同的角度来做更多的挖掘。谢谢。
0赞 Paul 8/2/2023
不知道刚才发生了什么。当我四处挖掘试图连接 ADO.Net 更新的工作原理时。我发现了一些大意是,您现在应该使用 MySql 而不是 MySqlConnector。它说不再支持 MySqlConnector。我在一个多月前开始了这个项目,我认为它说要改用 MySqlConnector。上个月有什么变化吗?我刚刚读过一些旧的东西吗?从 2023 年 7 月开始,还有一个新的 MySql 版本。在重新调试我的包装器以使用 MySql 后,它首先尝试开箱即用。

答: 暂无答案