2012-01-27 7 views
82

у меня есть:Как изменить тип данных DataColumn в DataTable?

DataTable Table = new DataTable; 
SqlConnection = new System.Data.SqlClient.SqlConnection("Data Source=" + ServerName + ";Initial Catalog=" + DatabaseName + ";Integrated Security=SSPI; Connect Timeout=120"); 

SqlDataAdapter adapter = new SqlDataAdapter("Select * from " + TableName, Connection); 
adapter.FillSchema(Table, SchemaType.Source); 
adapter.Fill(Table); 

DataColumn column = DataTable.Columns[0]; 

То, что я хочу сделать, это:

Предположим, в настоящее время column.DataType.Name является "Double". Я хочу, чтобы это стало "Int32".

Как это достичь?

Благодарим за отзыв, если они есть.

ответ

211

Вы не можете изменить DataType после заполнения Datatable данными. Однако вы можете клонировать таблицу данных, изменять тип столбца и загружать данные из предыдущей таблицы данных в клонированную таблицу, как показано ниже.

DataTable dtCloned = dt.Clone(); 
dtCloned.Columns[0].DataType = typeof(Int32); 
foreach (DataRow row in dt.Rows) 
{ 
    dtCloned.ImportRow(row); 
} 
+0

Спасибо, вы поможете мне здесь. Я твой должник :). – rofans91

+0

рад, что я мог помочь :) – Akhil

+0

Это помогло мне работать над важными данными. Благодарю. :) – AceMark

4

После заполнения DataTable вы не можете изменить тип столбца.

Ваш лучший вариант в этом случае заключается в добавлении Int32 колонки в DataTable перед заполнением его:

dataTable = new DataTable("Contact"); 
dataColumn = new DataColumn("Id"); 
dataColumn.DataType = typeof(Int32); 
dataTable.Columns.Add(dataColumn); 

Затем вы можете клонировать данные из исходной таблицы в новую таблицу:

DataTable dataTableClone = dataTable.Clone(); 

Вот post with more details.

22

Хотя это правда, что вы не можете изменить тип столбца после DataTable заполнена, вы можете изменить его после того, как вы называете FillSchema, но перед тем, как вызывать Fill. Например, скажем, третий столбец, который вы хотите конвертировать double в Int32, вы можете использовать:

adapter.FillSchema(table, SchemaType.Source); 
table.Columns[2].DataType = typeof (Int32); 
adapter.Fill(table); 
+1

Обратите внимание, что это не работает, если команда вашего адаптера является хранимой процедурой –

7

Рассмотрим также изменения типа возвращаемого:

select cast(columnName as int) columnName from table 
7
Dim tblReady1 As DataTable = tblReady.Clone() 

'' convert all the columns type to String 
For Each col As DataColumn In tblReady1.Columns 
    col.DataType = GetType(String) 
Next 

tblReady1.Load(tblReady.CreateDataReader) 
3

если вы хотите для изменения только столбца. Например, из строки в int32 вы можете использовать выражение.

DataColumn col = new DataColumn("col_int" , typeof(int)); 
table.columns.Add(col) 
col.Expression = "table_exist_col_string"; // digit string convert to int 
6

Я принял совсем другой подход. Мне нужно было проанализировать datetime из импорта excel, который был в формате даты OA. Эта методология достаточно проста для создания из ...в сущности,

  1. Добавить столбец типа вы хотите
  2. Rip через ряды преобразование значения
  3. Удаление исходного столбца и переименовать новый, чтобы соответствовать старому

    private void ChangeColumnType(System.Data.DataTable dt, string p, Type type){ 
         dt.Columns.Add(p + "_new", type); 
         foreach (System.Data.DataRow dr in dt.Rows) 
         { // Will need switch Case for others if Date is not the only one. 
          dr[p + "_new"] =DateTime.FromOADate(double.Parse(dr[p].ToString())); // dr[p].ToString(); 
         } 
         dt.Columns.Remove(p); 
         dt.Columns[p + "_new"].ColumnName = p; 
        } 
    
1

Я создал функцию расширения, которая позволяет изменять тип столбца DataTable. Вместо клонирования всей таблицы и импорта всех данных она просто клонирует столбец, анализирует значение и затем удаляет оригинал.

/// <summary> 
    /// Changes the datatype of a column. More specifically it creates a new one and transfers the data to it 
    /// </summary> 
    /// <param name="column">The source column</param> 
    /// <param name="type">The target type</param> 
    /// <param name="parser">A lambda function for converting the value</param> 
    public static void ChangeType(this DataColumn column, Type type, Func<object, object> parser) 
    { 
     //no table? just switch the type 
     if (column.Table == null) 
     { 
      column.DataType = type; 
      return; 
     } 

     //clone our table 
     DataTable clonedtable = column.Table.Clone(); 

     //get our cloned column 
     DataColumn clonedcolumn = clonedtable.Columns[column.ColumnName]; 

     //remove from our cloned table 
     clonedtable.Columns.Remove(clonedcolumn); 

     //change the data type 
     clonedcolumn.DataType = type; 

     //change our name 
     clonedcolumn.ColumnName = Guid.NewGuid().ToString(); 

     //add our cloned column 
     column.Table.Columns.Add(clonedcolumn); 

     //interpret our rows 
     foreach (DataRow drRow in column.Table.Rows) 
     { 
      drRow[clonedcolumn] = parser(drRow[column]); 
     } 

     //remove our original column 
     column.Table.Columns.Remove(column); 

     //change our name 
     clonedcolumn.ColumnName = column.ColumnName; 
    } 
} 

Вы можете использовать его так:

List<DataColumn> lsColumns = dtData.Columns 
    .Cast<DataColumn>() 
    .Where(i => i.DataType == typeof(decimal)) 
    .ToList() 

//loop through each of our decimal columns 
foreach(DataColumn column in lsColumns) 
{ 
    //change to double 
    column.ChangeType(typeof(double),(value) => 
    { 
     double output = 0; 
     double.TryParse(value.ToString(), out output); 
     return output; 
    }); 
} 

Приведенный выше код изменяет все десятичные столбцы двойников.

0
DataTable DT = ... 
// Rename column to OLD: 
DT.Columns["ID"].ColumnName = "ID_OLD"; 
// Add column with new type: 
DT.Columns.Add("ID", typeof(int)); 
// copy data from old column to new column with new type: 
foreach(DataRow DR in DT.Rows) 
{ DR["ID"] = Convert.ToInt32(DR["ID_OLD"]); } 
// remove "OLD" column 
DT.Columns.Remove("ID_OLD"); 
5

Старый пост, но я думал, что взвешиваются с DataTable расширением, которое может преобразовать один столбец в то время, к данному типу:

public static class DataTableExt 
{ 
    public static void ConvertColumnType(this DataTable dt, string columnName, Type newType) 
    { 
     using (DataColumn dc = new DataColumn(columnName + "_new", newType)) 
     { 
      // Add the new column which has the new type, and move it to the ordinal of the old column 
      int ordinal = dt.Columns[columnName].Ordinal; 
      dt.Columns.Add(dc); 
      dc.SetOrdinal(ordinal); 

      // Get and convert the values of the old column, and insert them into the new 
      foreach (DataRow dr in dt.Rows) 
       dr[dc.ColumnName] = Convert.ChangeType(dr[columnName], newType); 

      // Remove the old column 
      dt.Columns.Remove(columnName); 

      // Give the new column the old column's name 
      dc.ColumnName = columnName; 
     } 
    } 
} 

Затем он может быть называется так:

MyTable.ConvertColumnType("MyColumnName", typeof(int)); 

конечно, используя любой тип вы хотите, если каждое значение в столбце фактически могут быть преобразованы в новый тип.