1

OleDb 接続を介して MS Access データベースを更新する既存の方法があります。過去にこのメソッドを使用してデータを更新しましたが、アクセス テーブル (長いバイナリ データとして格納された OLE オブジェクト) にイメージ フィールドを追加したため、型の不一致エラーが発生しました。アクセス データベースからデータを取得するには、OleDbdataAdapter の標準的なものから DataTable を入力します。データベースから画像を取得して完璧に表示できるので、画像が正しく保存されていることがわかります。

DataTable の値をファイル データベースに更新するために、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;
        }
    }
4

1 に答える 1

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);

学んだ教訓。

于 2013-06-18T12:58:18.690 に答える