SQLBULKCOPY бросает систему. Formatexception при запуске writeToserver (datatable)
-
08-10-2019 - |
Вопрос
В настоящее время я пишу метод для чтения данных из файла CSV и импортировать в таблицу SQL.
DataTable dt = new DataTable();
String line = null;
int i = 0;
while ((line = reader.ReadLine()) != null)
{
String[] data = line.Split(',');
if (data.Length > 0)
{
if (i == 0)
{
foreach (object item in data)
{
DataColumn c = new DataColumn(Convert.ToString(item));
if (Convert.ToString(item).Contains("DATE"))
{
c.DataType = System.Type.GetType("System.DateTime");
}
else { c.DataType = System.Type.GetType("System.String"); }
dt.Columns.Add(c);
}
i++;
}
else
{
DataRow row = dt.NewRow();
for (int j = 0; j < data.Length; j++)
{
if (dt.Columns[j].DataType == System.Type.GetType("System.DateTime"))
{
row[j] = Convert.ToDateTime(data[j]);
}
else
{
row[j] = data[j];
}
}
dt.Rows.Add(row);
}
}
}
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings[Constant.CONNECTION_STRING_NAME].ConnectionString);
SqlBulkCopy s = new SqlBulkCopy(con);
s.DestinationTableName = "abc";
con.Open();
s.WriteToServer(dt);
Проблема при запуске этого метода исключение всегда брошена на S.WRITETOSERVER (DT); говорить
System.formatexception: строка не была распознана как действительное значение dateTime. Есть неизвестное слово, начиная с индекса 0.
Я отлажил и посмотрю, что все данные были загружены в DataTable правильно. Вот пример строки данных в моем файле CSV
DATA_VENDOR_ID,DATA_VENDOR_SUB_ID,DATA_VENDOR_CLIENT_ID,DATA_VENDOR_ACTIVITY_CODE,ACTIVITY_NAME,EFFECTIVE_DATE,ACTIVITY_LEVEL1,ACTIVITY_LEVEL2,ACTIVITY_LEVEL3,ACTIVITY_LEVEL4,ACTIVITY_LEVEL5,PARTICIPANT_ID,DATA_VENDOR_ALT_ID,FILE_CREATION_DATE,INC_VALUE
V01,,22097,ABCD01,Physical Activity,10/01/2010,Entertain Kiosk,ABCD - EFG 54,30,,AB01,W1234567891,,08/07/2006,100
и моя схема SQL таблицы:
RowID int Unique/AutoIncrement
DataVendorId varchar(32)
DataVendorSubId varchar(32)
DataVendorClientId varchar(32)
DataVendorActivityCode varchar(32)
ActivityName varchar(64)
EffectiveDate datetime
ActivityLevel1 varchar(253)
ActivityLevel2 varchar(253)
ActivityLevel3 varchar(253)
ActivityLevel4 varchar(253)
ActivityLevel5 varchar(253)
ParticipantID varchar(32)
DataVendorAltId varchar(32)
FileCreationDate datetime
IncValue varchar(5)
CreatedDate datetime optional/allow null
ModifiedDate datetime optional/allow null
Решение
Первая проблема, которую я вижу, это то, что у вас будут проблемы с RowID
столбец; Я ожидаю, что он пытается компенсировать ваши данные одним столбцом на данный момент - это не знает что вы их пропускаете. Вы можете либо беспорядок с отображениями, либо (в вашей таблице данных) добавить RowID
Столбец (по индексу 0) - но обратите внимание, что SQL Server будет игнорировать значения, если вы не включаете идентификатор-вставку.
Возможно попробуйте более явное преобразование TateTime:
row[j] = DateTime.ParseExact(data[j], "dd/MM/yyyy", CultureInfo.InvariantCulture);
Обратите внимание, что я не могу сказать из данных, если это DD / мм или мм / дд, поэтому вам может потребоваться настроить это.
Другие советы
У меня была похожая проблема, где были выключены колонны, и как только я определил сопоставление, без проблем:
using (SqlBulkCopy sbc = new SqlBulkCopy(ConfigurationManager.ConnectionStrings["SQLDatabase"].ConnectionString, SqlBulkCopyOptions.KeepIdentity))
{
sbc.DestinationTableName = "DestinationTable";
sbc.ColumnMappings.Add("foo", "bar");
sbc.ColumnMappings.Add("hello", "world");
sbc.ColumnMappings.Add("col1", "col2");
sbc.WriteToServer(data);
}
Кроме того, у меня есть список для расширения преобразователя DataTable, которое я использую для преобразования моего списка.
public static DataTable ToDataTable<T>(this IEnumerable<T> data)
{
PropertyDescriptorCollection properties =
TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
foreach (PropertyDescriptor prop in properties)
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
foreach (T item in data)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
row[prop.Name] = GetDataValue(prop.GetValue(item));
table.Rows.Add(row);
}
return table;
}
Метод GetDatavalue () очищает мои данные для дат Minvalue и т. Д.:
private static object GetDataValue(object value)
{
if (value == null || (value.GetType() == typeof(DateTime) && Convert.ToDateTime(value) == DateTime.MinValue) || (value.GetType() == typeof(DateTime) && Convert.ToDateTime(value) < Convert.ToDateTime("01/01/1753")))
{
return DBNull.Value;
}
return value;
}
Поля в вашем файле данных не соответствует таблице, т. Е. Вы пытаетесь вставить DataVendorId
в RowId
столбец, который вызывает исключение, поскольку вы не можете преобразовать varchar(32)
чтобы int
.
Переместите столбец вашего удостоверения личности до конца таблицы. Теперь объемная вставка сможет соответствовать всем полям до Это достигает функции идентификации.