清除 DataTable 中的 Byte[] 值时,OleDb Update 命令引发数据类型不匹配

Posted

技术标签:

【中文标题】清除 DataTable 中的 Byte[] 值时,OleDb Update 命令引发数据类型不匹配【英文标题】:OleDb Update command throws data type mismatch when clearing Byte[] value in DataTable 【发布时间】:2013-06-17 17:20:49 【问题描述】:

我有一种通过 OleDb 连接更新 MS Access 数据库的现有方法。我过去曾使用此方法更新数据,但现在我已将图像字段添加到访问表(OLE 对象存储为长二进制数据)中,因此出现类型不匹配错误。为了从 access 数据库中检索数据,我从标准的 OleDbdataAdapter 中填充了一个 DataTable。我可以从数据库中提取图像并让它完美显示,所以我知道它被正确存储了。

为了将数据表中的值更新到文件数据库中,我从数据表字段动态构建更新命令,并为每个字段包含参数。要将字段类型从系统类型映射到 OleDbType,我使用了一个返回所需类型的简单 switch 方法。

除了我想从 DataTable 中的特定行清除图像字段,然后更新数据库时,一切都按应有的方式工作。 DataTable 显示正确的空值,但是当调用更新命令时会引发此错误。我已经尝试将字段的值设置为 string.empty、null 和 DbNull.Value,均无济于事。

我必须以 SQL 'DELETE FROM' 的格式创建一个完全独立的方法吗?似乎这首先会破坏将其链接到 DataTable 的目的,但我当然不是这个主题的权威。提前感谢您的任何建议。

以下是我用来参考的方法:

更新 Db 表:

    public static bool UpdateDbTable(string dbPath, string rowFilter, DataTable inputTable)
    
        // Create the connection
        using (var connection = GetConnection(dbPath))
        
            try
            
                // Open the connection
                connection.Open();

                // Create the update command
                var updateCommand = GetUpdateCommand(inputTable, rowFilter, connection);

                // Link the new data adapter
                var adapter = new OleDbDataAdapter  UpdateCommand = updateCommand ;

                // Update the MDB table
                adapter.Update(inputTable);

             // Return false on error
            catch (OleDbException)
            
                return false;
            
        

        // Return true on success
        return true;
    

构建更新命令:

    private static OleDbCommand GetUpdateCommand(DataTable inputTable, string rowFilter, OleDbConnection connection)
    
        // Create the return command
        var retCommand = connection.CreateCommand();

        // Build the command string
        var sb = new StringBuilder(string.Format("UPDATE 0 SET ", inputTable.TableName));

        foreach (DataColumn col in inputTable.Columns)
        
            // Append the command text
            sb.AppendFormat("0 = ?, ", col.ColumnName);

            // Create the column parameter
            var par = new OleDbParameter
                
                    ParameterName = col.ColumnName,
                    OleDbType = GetOleDbType(col.DataType),
                    Size = col.MaxLength,
                    SourceColumn = col.ColumnName
                ;

            // Set any null values to DBNull
            if (par.Value == null) par.Value = DBNull.Value;

            // Add the parameter to the return command
            retCommand.Parameters.Add(par);
        

        // Remove the last comma
        sb.Remove(sb.ToString().LastIndexOf(','), 1);

        // Add a where clause if a rowfilter was provided
        if (rowFilter != string.Empty)
            sb.AppendFormat("WHERE 0", rowFilter);

        // Set the command text
        retCommand.CommandText = sb.ToString();

        // Return the command
        return retCommand;
    

映射正确的数据类型:

    private static OleDbType GetOleDbType(Type inputType)
    
        switch (inputType.FullName)
        
            // Return the appropriate type
            case "System.Boolean":
                return OleDbType.Boolean;
            case "System.Int32":
                return OleDbType.Integer;
            case "System.Single":
                return OleDbType.Single;
            case "System.Double":
                return OleDbType.Double;
            case "System.Decimal":
                return OleDbType.Decimal;
            case "System.String":
                return OleDbType.Char;
            case "System.Char":
                return OleDbType.Char;
            case "System.Byte[]":
                return OleDbType.Binary;
            default:
                return OleDbType.Variant;
        
    

【问题讨论】:

【参考方案1】:

今天早上发现了我的问题。我传递给 GetUpdateCommand 的“rowFilter”字符串导致了问题。我复制了这样的早期格式:

var rowFilter = string.Format("tag_unique_id = '0'", curTag);

我过去曾使用过这种类型的过滤器来查找文本值。因此,围绕字段值的单引号导致适配器将其解释为 WHERE 子句中的字符串。由于 tag_unique_id 字段是 int32,它当然会在运行时引发类型不匹配错误。解决方案是像这样去掉引号:

var rowFilter = string.Format("tag_unique_id = 0", curTag);

经验教训。

【讨论】:

以上是关于清除 DataTable 中的 Byte[] 值时,OleDb Update 命令引发数据类型不匹配的主要内容,如果未能解决你的问题,请参考以下文章

搜索之后,p:dataTable将不会更新,除非调用两次搜索或者输入和清除过滤器中的某些内容

每次使用 access vba 在第一个组合中选择值时,清除链接组合框中的值

<p:dataTable> 中的 sortMode="multiple" 和 lazy="true" 在分页期间清除多排序元数据

C# 无法将类型为“System.Byte[]”的对象强制转换为类型“System.Data.DataTable

如何从 DataTable 中的最后一行检索值?

C# DataTable.Rows.Clear() 不清除行[重复]