2012-01-27 14 views
82

ho:Come modificare DataType di DataColumn in un 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]; 

Quello che voglio fare è:

supponga attualmente column.DataType.Name è "Double". Voglio che diventi "Int32".

Come ottengo questo?

Grazie per la risposta, se presente.

risposta

211

Non è possibile modificare il DataType dopo che Datatable è stato riempito con i dati. Tuttavia, è possibile clonare la tabella Dati, modificare il tipo di colonna e caricare i dati dalla tabella di dati precedente alla tabella clonata, come illustrato di seguito.

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

Grazie fratello mi aiuti qui. Ti devo un favore :). – rofans91

+0

felice di poter aiutare :) – Akhil

+0

Questo mi ha aiutato a lavorare su dati importanti. Grazie. :) – AceMark

4

Una volta riempito uno DataTable, non è possibile modificare il tipo di una colonna.

La soluzione migliore in questo scenario è quello di aggiungere una colonna Int32 al DataTable prima di riempirlo:

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

Quindi è possibile clonare i dati dal vostro tavolo originale per la nuova tabella:

DataTable dataTableClone = dataTable.Clone(); 

Ecco uno post with more details.

22

Se è vero che non è possibile modificare il tipo di colonna dopo l'DataTable è pieno, è possibile modificarlo dopo aver chiamato FillSchema, ma prima di chiamare Fill. Ad esempio, dire la terza colonna è quello che si desidera convertire double-Int32, è possibile utilizzare:

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

Si noti che questo non sembra funzionare se il comando dell'adattatore è una stored procedure –

7

Considera anche alterare il tipo di ritorno:

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

se si desidera per cambiare solo una colonna. Per esempio da string a int32 puoi usare expression.

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

Ho adottato un approccio un po 'diverso. Avevo bisogno di analizzare un datetime da un'importazione excel che era nel formato data OA. Questa metodologia è abbastanza semplice da costruire da ...in sostanza,

  1. Aggiungi colonna del tipo che si desidera
  2. Rip attraverso le righe convertendo il valore
  3. eliminare la colonna originale e rinominare il nuovo modo che corrisponda al vecchio

    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

Ho creato una funzione di estensione che consente di modificare il tipo di colonna di un DataTable. Invece di clonare l'intera tabella e importare tutti i dati, clona semplicemente la colonna, analizza il valore e quindi elimina l'originale.

/// <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; 
    } 
} 

Si può usare in questo modo:

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; 
    }); 
} 

Il codice sopra cambia tutte le colonne decimali da doppie.

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

Vecchio post, ma ho pensato di pesare, con un'estensione DataTable che può convertire una singola colonna alla volta, per un dato tipo:

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; 
     } 
    } 
} 

Può quindi essere chiamato in questo modo:

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

Naturalmente utilizzando qualsiasi tipo che desideri, a patto che ogni valore nella colonna può effettivamente essere convertito nel nuovo tipo.

Problemi correlati