前回の記事では、バッチ追加操作をテストしていましたが、一貫した追加が失敗し、最終的にはフィールド列の順序が矛盾していることがわかりました。
1. 一貫性のない列名
1.1. エラーメッセージ
デバッグ中、次のエラー メッセージが常に表示されました。データと型を比較した後、問題は見つかりませんでした。分析後、最初の列は GUID 文字列で、テーブルの最初のフィールドは自動インクリメント ID を持つ整数です。これは、次のプロンプト メッセージを説明できます:
データ ソースからの String 型の指定された値を、指定されたターゲット列の int 型に変換できないことを意味します。
1.2. 解決策
SqlBulkCopy を使用して DataTable をバッチで追加する場合、DataTable の列がデータベース テーブルの列と一致していることを確認することが非常に重要です。
満たさなければならない要件は次のとおりです。
1) 列名を一致させます。DataTable の列名はデータベース テーブルの列名と一致している必要があります。列名の大文字と小文字のスペルが正しいことを確認してください。
2) 列の数: DataTable の列の数は、データベース テーブルの列の数と一致している必要があります。
3) データ型の一致: DataTable の列のデータ型は、データベース テーブルの列のデータ型と一致する必要があります。データ型に互換性があり、正しく変換できることを確認してください。
DataTable の列がデータベース テーブルの列と一致しない場合、SqlBulkCopy 操作が失敗するか、データ挿入エラーが発生する可能性があります。
DataTable 列の名前を変更する場合は、マッピングに ColumnMapping を使用できます。
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
// 创建一个 DataTable 并填充数据
DataTable dataTable = CreateDataTable();
// 创建一个 SqlBulkCopy 对象
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
{
bulkCopy.DestinationTableName = "YourDestinationTableName";
// 映射 DataTable 的列到数据库表的列
bulkCopy.ColumnMappings.Add("SourceColumn1", "DestinationColumn1");
bulkCopy.ColumnMappings.Add("SourceColumn2", "DestinationColumn2");
// 执行批量插入
bulkCopy.WriteToServer(dataTable);
}
}
前述のコードでは、DataTable 列の名前をターゲット テーブルの列名にマップし、マップされた列の数とデータ型が正しく一致していることを確認します。
要約すると、DataTable をバッチで正常に追加するには、DataTable の列がデータベース テーブルの列と一致していることを確認してください。ColumnMappings を使用して、列名が一致しない場合に動作するように列名をマップすることもできます。
2. 自動インクリメント列を閉じる
DataTable データをバッチで追加するときに、自己インクリメント ID 列を処理する必要がある場合は、次の 2 つの一般的な方法を使用できます。
2.1、列は含まれません
ターゲット テーブルの自己インクリメント機能を無効にする:
ターゲット テーブルの ID 列の自己インクリメント機能を無効にし、SqlBulkCopy の操作時にマッピングにソース テーブルの ID 列を含めないようにします。このようにして、データベース エンジンは各行に新しい自動インクリメント ID を自動的に割り当てます。
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
// 创建一个 DataTable 并填充数据
DataTable dataTable = CreateDataTable();
// 创建一个 SqlBulkCopy 对象
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
{
bulkCopy.DestinationTableName = "YourDestinationTableName";
// 不包括源表的 ID 列在映射中
bulkCopy.ColumnMappings.Add("Column1", "Column1");
bulkCopy.ColumnMappings.Add("Column2", "Column2");
// 执行批量插入
bulkCopy.WriteToServer(dataTable);
}
}
上記のコードでは、ソース テーブルの ID 列を SqlBulkCopy のターゲット テーブルの ID 列としてマップする必要がないことを前提としています。データベース エンジンは、ターゲット テーブルに対して自動インクリメントされる ID 値を生成します。
2.2. 機能の終了
DataTable の自動インクリメント機能をオフにする:
ソース テーブルの自動インクリメント ID 列を保持してターゲット テーブルに挿入したいが、ターゲット テーブルの自動インクリメント ID との競合を避けたい場合は、 DataTable の自動インクリメント機能をオフにします。
// 创建一个 DataTable 并填充数据
DataTable dataTable = CreateDataTable();
// 关闭 ID 列的自增特性
dataTable.Columns["ID"].AutoIncrement = false;
dataTable.Columns["ID"].ReadOnly = true;
// 接下来使用 SqlBulkCopy 进行批量插入操作
ID 列の自動インクリメント機能をオフにした後、SqlBulkCopy はバッチ挿入中に ID 列を処理しませんが、ソース テーブルの値に従ってターゲット テーブルに ID 列を挿入します。
ID 列の自動インクリメントの問題に対処するには、特定のニーズに応じて適切な方法を選択する必要があります。一括挿入に SqlBulkCopy を使用する場合は、データ挿入の問題を避けるために、データベース テーブルの構造とソース テーブルのデータ型と列名が同じであることを確認し、列を正しくマップする必要があることに注意してください。