web-dev-qa-db-ja.com

colid 6のbcpクライアントから無効な列長を受け取りました

C#コードからSQL Server 2005にcsvファイルデータを一括アップロードしたいのですが、次のエラーが発生しています-

Colid 6のbcpクライアントから無効な列長を受け取りました。

一括コピーがデータベースサーバーに書き込む場合

70
Sana Sana

Excelのデータ列の1つ(列ID 6)には、データベースのデータ列のデータ型の長さを超える1つ以上のセルデータがあります。

Excelでデータを確認します。また、その形式がデータベーステーブルスキーマに準拠していることをExcelで確認します。

これを回避するには、データベーステーブルの文字列データ型のデータ長を超えてみてください。

お役に立てれば。

57
Dinesh

私はこの投稿が古いことを知っていますが、この同じ問題にぶつかり、最終的にどの列が問題を引き起こしているかを判断し、必要に応じて報告する解決策を見つけました。私はそれを決めた 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;
}
157
b_stil

一括挿入/コピーを実行しているテーブルの列のサイズを確認します。 varcharまたは他の文字列列を拡張する必要があるか、挿入する値をトリムする必要があります。列の順序も表と同じである必要があります。

例:varchar列のサイズを30から50に増やす=>

ALTER TABLE [dbo]。[TableName] ALTER COLUMN [ColumnName] Varchar(50)

1

SQL BulkCopyオプションを使用してデータベーステーブルに文字列を渡すときに、同様の問題に直面しました。渡された文字列は3文字でしたが、宛先列の長さはvarchar(20)でした。 Trim()関数を使用してDBに挿入する前に文字列をトリミングして、問題が文字列内のスペース(先頭と末尾)によるものかどうかを確認しました。文字列をトリミングした後、正常に機能しました。

text.Trim()を試すことができます

1
Liji Chandran

すばらしいコード、共有してくれてありがとう!

最終的にリフレクションを使用して、エラー時に実際の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;
}
0
infocyde