Cómo cambiar DataType de una DataColumn en una DataTable?

Yo tengo:

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

Lo que quiero hacer es:

Asum que actualmente column.DataType.Name es “Doble” . Quiero que se convierta en “Int32” .

¿Cómo logro esto?

No puede cambiar el tipo de datos después de que la tabla de datos esté llena de datos. Sin embargo, puede clonar la tabla de Datos, cambiar el tipo de columna y cargar los datos de la tabla de datos anterior a la tabla clonada como se muestra a continuación.

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

Si bien es cierto que no puede cambiar el tipo de columna después de que se llene DataTable , puede cambiarla después de llamar a FillSchema , pero antes de llamar a Fill . Por ejemplo, supongamos que la tercera columna es la que desea convertir de double a Int32 , puede usar:

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

Considere también la posibilidad de alterar el tipo de devolución:

 select cast(columnName as int) columnName from table 
 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) 

Publicación anterior, pero pensé en analizar, con una extensión DataTable que puede convertir una sola columna a la vez, en un tipo determinado:

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

Entonces se puede llamar así:

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

Por supuesto, utilizando el tipo que desee, siempre que cada valor en la columna se pueda convertir al nuevo tipo.

He tomado un enfoque diferente. Necesitaba analizar un datetime de una importación de Excel que estaba en el formato de fecha OA. Esta metodología es lo suficientemente simple como para construir desde … en esencia,

  1. Agrega la columna del tipo que quieras
  2. Ripear las filas convirtiendo el valor
  3. Elimine la columna original y cambie el nombre a la nueva para que coincida con la anterior

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

Una vez que se ha llenado una DataTable , no puede cambiar el tipo de una columna.

Su mejor opción en este escenario es agregar una columna Int32 a la DataTable antes de completarla:

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

Luego puede clonar los datos de su tabla original en la nueva tabla:

 DataTable dataTableClone = dataTable.Clone(); 

Aquí hay una publicación con más detalles .

si quiere cambiar solo una columna. Por ejemplo, de string a int32 puede usar expression.

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

Creé una función de extensión que permite cambiar el tipo de columna de una DataTable. En lugar de clonar toda la tabla e importar todos los datos, simplemente clona la columna, analiza el valor y luego elimina el original.

  ///  /// Changes the datatype of a column. More specifically it creates a new one and transfers the data to it ///  /// The source column /// The target type /// A lambda function for converting the value public static void ChangeType(this DataColumn column, Type type, Func 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; } } 

Puedes usarlo así:

 List lsColumns = dtData.Columns .Cast() .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; }); } 

El código anterior cambia todas las columnas decimales a dobles.

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