Comment changer le type de données D'une DataColumn dans un DataTable?

J'ai:

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

Ce que je veux faire est:

Supposons actuellement colonne.Type de données.Nom est "Double". Je veux qu'il devienne "Int32".

Comment puis-je y parvenir?

94
demandé sur Mitch Wheat 2012-01-27 05:49:46

10 réponses

Vous ne pouvez pas modifier le type de données après que le Datatable est rempli de données. Cependant, vous pouvez cloner la table de données, modifier le type de colonne et charger les données de la table de données précédente à la table clonée comme indiqué ci-dessous.

DataTable dtCloned = dt.Clone();
dtCloned.Columns[0].DataType = typeof(Int32);
foreach (DataRow row in dt.Rows) 
{
    dtCloned.ImportRow(row);
}
228
répondu Akhil 2012-01-27 01:56:49

S'il est vrai que vous ne pouvez pas changer le type de la colonne après que le DataTable est rempli, vous pouvez le changer après avoir appelé FillSchema, mais avant d'appeler Fill. Par exemple, disons que la 3ème colonne est celle que vous voulez convertir de double à Int32, vous pouvez utiliser:

adapter.FillSchema(table, SchemaType.Source);
table.Columns[2].DataType = typeof (Int32);
adapter.Fill(table);
24
répondu rsbarro 2012-01-27 02:04:11

Ancien post, mais je pensais peser, avec une extension DataTable qui peut convertir une seule colonne à la fois, à un type donné:

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

Il peut alors être appelé comme ceci:

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

Bien sûr, en utilisant le type que vous désirez, tant que chaque valeur de la colonne peut réellement être convertie en nouveau type.

9
répondu Marc Ferrold 2017-06-21 18:42:10

Pensez également à modifier le type de retour:

select cast(columnName as int) columnName from table
8
répondu tsilb 2013-07-02 19:49:53
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)
8
répondu Superna Parajuli 2014-08-27 23:45:53

J'ai adopté une approche un peu différente. J'avais besoin d'analyser un datetime à partir d'une importation excel au format de date OA. Cette méthodologie est assez simple pour construire à partir de... en substance,

  1. Ajouter une colonne du type que vous voulez
  2. parcourir les lignes en convertissant la valeur
  3. Supprimez la colonne d'origine et renommez la nouvelle pour correspondre à l'ancienne

    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;
        }
    
7
répondu John Salewski 2016-02-15 23:43:39

Une fois qu'un DataTable a été rempli, vous ne pouvez pas changer le type d'une colonne.

Votre meilleure option dans ce scénario est d'ajouter une colonne Int32 au DataTable avant de le remplir:

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

Ensuite, vous pouvez cloner les données de votre table d'origine vers la nouvelle table:

DataTable dataTableClone = dataTable.Clone();

Voici un message avec plus de détails .

4
répondu Josh Earl 2012-01-27 02:05:00

Si vous voulez changer seulement une colonne.par exemple, de string à int32, vous pouvez utiliser expression.

DataColumn col = new DataColumn("col_int" , typeof(int));
table.columns.Add(col)
col.Expression = "table_exist_col_string"; // digit string convert to int  
3
répondu mehdi 2015-09-21 07:48:42

J'ai créé une fonction d'extension qui permet de changer le type de colonne D'un DataTable. Au lieu de cloner la table entière et d'importer toutes les données, il clone simplement la colonne, analyse la valeur, puis supprime l'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;
    }
}

Vous pouvez l'utiliser comme ceci:

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

Le code ci-dessus change toutes les colonnes décimales en doubles.

2
répondu Wes Hanney 2017-05-24 01:11:47
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" );
0
répondu Altivo 2017-06-08 10:14:49