c# - que - Cómo cambiar DataType de una DataColumn en una DataTable?
new datacolumn c# (10)
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:
Asuma que actualmente column.DataType.Name es "Doble" . Quiero que se convierta en "Int32" .
¿Cómo logro esto?
Considere también la posibilidad de alterar el tipo de devolución:
select cast(columnName as int) columnName from table
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.
/// <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;
}
}
Puedes usarlo así:
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;
});
}
El código anterior cambia todas las columnas decimales a dobles.
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,
- Agrega la columna del tipo que quieras
- Ripear las filas convirtiendo el valor
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; }
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);
}
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.
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);
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
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" );
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)