Kacper Drapała

SqlBulkCopy i błąd „Received an invalid column…”

Received an invalid column length from the bcp client for colid x

Taki komunikat dostaniemy w momencie, kiedy będziemy próbować zapisać do naszego Bulka, tabelę w której jakaś komórka w jakimkolwiek wierszu jest za długa lub złego typu.

Problemem jest, że w InnerException nie posiadamy żadnej informacji mówiąca nam znacząco w którym wierszu mamy jakiś problem. Każdemu takiemu błędowi towarzyszy numer. W tym przypadku jest to 3. Ta liczba mówi nam w której kolumnie jest błąd.

Ciężko więc tylko po takiej informacji znaleźć problem. Rozwiązaniem jednak okazuje się dość prosta metoda.

protected string GetBulkCopyColumnException(Exception ex, SqlBulkCopy bulkcopy)
{
string message = string.Empty;
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);
message = (String.Format("Column: {0} contains data with a length greater than: {1}", column, length));
}
return message;
}

Dzieki tej metodze dowiemy się w łatwy sposób co jest przyczyną tego błędu.

Problemem okazała się zbyt długa wartość w 3 kolumnie. Dzieje się tak ponieważ jest robiony w kodzie zwykły insert tych danych z SqlBulka do kolumny, która w bazie jest zdefiniowana jako varchar(255).

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *