Wiem, że ten post jest stary, ale natknąłem się na ten sam problem i wreszcie znalazłem rozwiązanie, aby określić, która kolumna powoduje problem i zgłosić go w razie potrzeby. Ustaliłem, że colid
zwrócony w SqlException nie jest zerowy, więc musisz odjąć od niego 1, aby uzyskać wartość. Następnie jest używany jako indeks _sortedColumnMappings
ArrayList wystąpienia SqlBulkCopy, a nie indeks mapowań kolumn, które zostały dodane do wystąpienia SqlBulkCopy. Należy zauważyć, że SqlBulkCopy zatrzyma się po pierwszym otrzymanym błędzie, więc może to nie być jedyny problem, ale przynajmniej pomaga go rozwiązać.
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;
}