C#コードからSQL Server 2005にcsvファイルデータを一括アップロードしたいのですが、次のエラーが発生しています-
Colid 6のbcpクライアントから無効な列長を受け取りました。
一括コピーがデータベースサーバーに書き込む場合
Excelのデータ列の1つ(列ID 6)には、データベースのデータ列のデータ型の長さを超える1つ以上のセルデータがあります。
Excelでデータを確認します。また、その形式がデータベーステーブルスキーマに準拠していることをExcelで確認します。
これを回避するには、データベーステーブルの文字列データ型のデータ長を超えてみてください。
お役に立てれば。
私はこの投稿が古いことを知っていますが、この同じ問題にぶつかり、最終的にどの列が問題を引き起こしているかを判断し、必要に応じて報告する解決策を見つけました。私はそれを決めた colid
SqlExceptionで返される値はゼロベースではないため、値を取得するには1を引く必要があります。その後は、SqlBulkCopyインスタンスに追加された列マッピングのインデックスではなく、SqlBulkCopyインスタンスの_sortedColumnMappings
ArrayListのインデックスとして使用されます。注意すべきことの1つは、最初に受信したエラーでSqlBulkCopyが停止するため、これが唯一の問題ではないかもしれませんが、少なくともそれを把握するのに役立ちます。
try
{
bulkCopy.WriteToServer(importTable);
sqlTran.Commit();
}
catch (SqlException ex)
{
if (ex.Message.Contains("Received an invalid column length from the bcp client for colid"))
{
string pattern = @"\d+";
Match match = Regex.Match(ex.Message.ToString(), pattern);
var index = Convert.ToInt32(match.Value) -1;
FieldInfo fi = typeof(SqlBulkCopy).GetField("_sortedColumnMappings", BindingFlags.NonPublic | BindingFlags.Instance);
var sortedColumns = fi.GetValue(bulkCopy);
var items = (Object[])sortedColumns.GetType().GetField("_items", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(sortedColumns);
FieldInfo itemdata = items[index].GetType().GetField("_metadata", BindingFlags.NonPublic | BindingFlags.Instance);
var metadata = itemdata.GetValue(items[index]);
var column = metadata.GetType().GetField("column", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).GetValue(metadata);
var length = metadata.GetType().GetField("length", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).GetValue(metadata);
throw new DataFormatException(String.Format("Column: {0} contains data with a length greater than: {1}", column, length));
}
throw;
}
一括挿入/コピーを実行しているテーブルの列のサイズを確認します。 varcharまたは他の文字列列を拡張する必要があるか、挿入する値をトリムする必要があります。列の順序も表と同じである必要があります。
例:varchar列のサイズを30から50に増やす=>
ALTER TABLE [dbo]。[TableName] ALTER COLUMN [ColumnName] Varchar(50)
SQL BulkCopyオプションを使用してデータベーステーブルに文字列を渡すときに、同様の問題に直面しました。渡された文字列は3文字でしたが、宛先列の長さはvarchar(20)
でした。 Trim()
関数を使用してDBに挿入する前に文字列をトリミングして、問題が文字列内のスペース(先頭と末尾)によるものかどうかを確認しました。文字列をトリミングした後、正常に機能しました。
text.Trim()
を試すことができます
すばらしいコード、共有してくれてありがとう!
最終的にリフレクションを使用して、エラー時に実際のDataMemberNameをクライアントに返送しました(WCFサービスで一括保存を使用しています)。うまくいけば、他の誰かが私がそれをどのように役立てたかを見つけるでしょう。
static string GetDataMemberName(string colName, object t) {
foreach(PropertyInfo propertyInfo in t.GetType().GetProperties()) {
if (propertyInfo.CanRead) {
if (propertyInfo.Name == colName) {
var attributes = propertyInfo.GetCustomAttributes(typeof(DataMemberAttribute), false).FirstOrDefault() as DataMemberAttribute;
if (attributes != null && !string.IsNullOrEmpty(attributes.Name))
return attributes.Name;
return colName;
}
}
}
return colName;
}