105 votes

A reçu une longueur de colonne non valide du client bcp pour colid 6

Je veux télécharger en masse les données d'un fichier csv vers sql server 2005 à partir du code c# mais je rencontre l'erreur suivante -

Reçu une longueur de colonne invalide de la part du client bcp pour colid 6.

lorsque l'écriture en vrac se fait sur le serveur de base de données

0voto

infocyde Points 1878

Super morceau de code, merci de le partager!

J'ai fini par utiliser la réflexion pour obtenir le DataMemberName réel à renvoyer à un client en cas d'erreur (j'utilise l'enregistrement en masse dans un service WCF). Espérons que quelqu'un d'autre trouvera utile ce que j'ai fait.

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

0voto

flashgordon Points 5

J'ai reçu ce message d'erreur avec une version ssis beaucoup plus récente (vs 2015 entreprise, je pense que c'est ssis 2016). Je vais commenter ici car c'est la première référence qui apparaît lorsque vous recherchez ce message d'erreur. Je pense que cela se produit surtout avec les colonnes de caractères lorsque la taille de caractère source est plus grande que la taille de caractère cible. J'ai reçu ce message lorsque j'utilisais une entrée ado.net vers ms sql à partir d'une base de données teradata. Drôle, car les précédentes écritures oledb vers ms sql géraient parfaitement toutes les conversions de caractères sans aucune substitution de code. Le numéro de ColId et le numéro de colonne d'entrée de destination correspondant que vous obtenez parfois avec le message ColId sont inutiles. Ce n'est pas la colonne lorsque vous comptez depuis le haut de la correspondance ou quoi que ce soit de ce genre. Si j'étais Microsoft, je serais gêné de donner un message d'erreur qui semble pointer sur la colonne du problème alors que ce n'est pas le cas. J'ai trouvé le ColId du problème en faisant une supposition éclairée, puis en changeant l'entrée de la correspondance en "Ignorer" puis en relançant pour voir si le message disparaissait. Dans mon cas et dans mon environnement, je l'ai corrigé en réduisant la taille du caractère de l'entrée Teradata à la taille de caractère de la déclaration ms sql pour la colonne de sortie. Vérifiez et assurez-vous que votre sous-chaîne d'entrée se propage à travers toutes vos conversions de données et vos correspondances. Dans mon cas, ce n'était pas le cas et j'ai dû supprimer toutes mes conversions de données et mes correspondances et recommencer. Encore une fois, il est drôle qu'OleDB ait simplement géré cela et qu'ado.net ait lancé l'erreur et ait dû intervenir autant pour le résoudre. En général, vous devriez utiliser OLEDB lorsque votre cible est MS Sql.

0voto

Ahmad Tijani Points 362

Je suis tombé sur ceci et en utilisant l'extrait de @b_stil, j'ai pu identifier la colonne coupable. Et après une enquête plus poussée, j'ai réalisé que je devais également redimensionner la colonne comme l'a suggéré @Liji Chandran, mais j'utilisais IExcelDataReader et je ne pouvais pas trouver de moyen facile pour valider et redimensionner chacune de mes 160 colonnes.

Ensuite, je suis tombé sur cette classe, (ValidatingDataReader) de CSVReader.

La chose intéressante à propos de cette classe est qu'elle vous donne la longueur des données des colonnes source et destination, la ligne coupable et même la valeur de la colonne qui cause l'erreur.

Tout ce que j'ai fait était de redimensionner toutes les colonnes (nvarchar, varchar, char et nchar).

J'ai simplement modifié ma méthode GetValue comme ceci :

 object IDataRecord.GetValue(int i)
    {
        object columnValue = reader.GetValue(i);

        if (i > -1 && i < lookup.Length)
        {
            DataRow columnDef = lookup[i];
            if
            (
                (
                    (string)columnDef["DataTypeName"] == "varchar" ||
                    (string)columnDef["DataTypeName"] == "nvarchar" ||
                    (string)columnDef["DataTypeName"] == "char" ||
                    (string)columnDef["DataTypeName"] == "nchar"
                ) &&
                (
                    columnValue != null &&
                    columnValue != DBNull.Value
                )
            )
            {
                string stringValue = columnValue.ToString().Trim();

                columnValue = stringValue;

                if (stringValue.Length > (int)columnDef["ColumnSize"])
                {
                    string message =
                        "Valeur de la colonne \"" + stringValue.Replace("\"", "\\\"") + "\"" +
                        " avec une longueur de " + stringValue.Length.ToString("###,##0") +
                        " de la colonne source " + (this as IDataRecord).GetName(i) +
                        " dans l'enregistrement " + currentRecord.ToString("###,##0") +
                        " ne rentre pas dans la colonne de destination " + columnDef["ColumnName"] +
                        " avec une longueur de " + ((int)columnDef["ColumnSize"]).ToString("###,##0") +
                        " dans la table " + tableName +
                        " de la base de données " + databaseName +
                        " sur le serveur " + serverName + ".";

                    if (ColumnException == null)
                    {
                        throw new Exception(message);
                    }
                    else
                    {
                        ColumnExceptionEventArgs args = new ColumnExceptionEventArgs();

                        args.DataTypeName = (string)columnDef["DataTypeName"];
                        args.DataType = Type.GetType((string)columnDef["DataType"]);
                        args.Value = columnValue;
                        args.SourceIndex = i;
                        args.SourceColumn = reader.GetName(i);
                        args.DestIndex = (int)columnDef["ColumnOrdinal"];
                        args.DestColumn = (string)columnDef["ColumnName"];
                        args.ColumnSize = (int)columnDef["ColumnSize"];
                        args.RecordIndex = currentRecord;
                        args.TableName = tableName;
                        args.DatabaseName = databaseName;
                        args.ServerName = serverName;
                        args.Message = message;

                        ColumnException(args);

                        columnValue = args.Value;
                    }
                }

            }
        }

        return columnValue;
    }

J'espère que cela aidera quelqu'un

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X