Изменение заполненных типов столбцов данных DataTable
У меня есть System.Data.DataTable, который заполняется чтением CSV файла, который устанавливает тип данных каждого столбца в строку.
Я хочу добавить содержимое DataTable в существующую таблицу базы данных - в настоящее время это делается с использованием SqlBulkCopy с DataTable в качестве источника.
Однако типы данных столбцов DataTable необходимо изменить, чтобы они соответствовали схеме таблицы целевой базы данных, обрабатывая нулевые значения.
Я не очень хорошо знаком с ADO.NET, поэтому я искал чистый способ сделать это?
Спасибо.
Ответы
Ответ 1
Вы не можете изменить DataType
DataColumn
после заполнения его данными. Это не свойство только для чтения, но вы получите исключение во время выполнения, если попытаетесь изменить его после того, как у него уже есть данные.
В документации :
Исключение генерируется при изменении этого свойства после того, как столбец начал хранить данные.
Поэтому вам нужно либо обеспечить правильные типы столбцов в начале (если возможно), либо создать новый DataTable
специально для импорта и копирования данных из оригинала DataTable
.
Вы также можете написать собственный класс IDataReader
, который читает с вашего DataTable
и выполняет преобразование "точно в срок" и передает его в SqlBulkCopy
- это будет намного более эффективно, но это, очевидно, не быстрое исправление.
Ответ 2
Я написал эту общую функцию для выполнения этой работы, она очень хорошо работает для меня:
public static bool ChangeColumnDataType(DataTable table, string columnname, Type newtype)
{
if (table.Columns.Contains(columnname) == false)
return false;
DataColumn column= table.Columns[columnname];
if (column.DataType == newtype)
return true;
try
{
DataColumn newcolumn = new DataColumn("temporary", newtype);
table.Columns.Add(newcolumn);
foreach (DataRow row in table.Rows)
{
try
{
row["temporary"] = Convert.ChangeType(row[columnname], newtype);
}
catch
{
}
}
table.Columns.Remove(columnname);
newcolumn.ColumnName = columnname;
}
catch (Exception)
{
return false;
}
return true;
}
Вы можете просто скопировать код и поместить его в класс (MyClass здесь) и использовать его следующим образом:
MyClass.ChangeColumnDataType(table, "GEOST", typeof (int));
Ответ 3
Обязательно укажите типы данных, которые вы заполняете.
например:.
DataTable table = new DataTable("countries");
table.Columns.Add("country_code", typeof (string));
table.Columns.Add("country_name", typeof (string));
//...
//Fill table
Или вы можете изменить типы столбцов, если они совместимы:
table.Columns["country_code"].DataType = typeof(string);
Ответ 4
Если вы заполняете файл csv, сначала прочитайте схему в datatable, затем измените тип данных столбца, а затем заполните таблицу.
Пример. Я использую XML файл для импорта данных.
DataSet dstemp = new DataSet();
dstemp.ReadXmlSchema(@"D:\path of file\filename.xml");
dstemp.Tables[0].Columns["Student_id"].DataType = typeof(Guid);
dstemp.ReadXml(@"D:\path of file\filename.xml");
Думаю, это сработает для вас.
Ответ 5
Так же, как "Eddie Monge Jr" или "Gisway" не может получить его.
но с правильным порядком столбцов.
public static bool ChangeColumnDataType(DataTable table, string columnname, Type newtype){
if (table.Columns.Contains(columnname) == false)
return false;
DataColumn column = table.Columns[columnname];
if (column.DataType == newtype)
return true;
try{
DataColumn newcolumn = new DataColumn("temporary", newtype);
table.Columns.Add(newcolumn);
foreach (DataRow row in table.Rows){
try{
row["temporary"] = Convert.ChangeType(row[columnname], newtype);
}
catch{}
}
newcolumn.SetOrdinal(column.Ordinal);
table.Columns.Remove(columnname);
newcolumn.ColumnName = columnname;
}
catch (Exception){
return false;
}
return true;
}