如何更改DataTable中DataColumn的DataType?

rof*_*s91 112 c# datatable types datacolumn

我有:

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];
Run Code Online (Sandbox Code Playgroud)

我想做的是:

假设当前column.DataType.Name"Double".我希望它成为"Int32".

我该如何实现这一目标?

Akh*_*hil 255

在数据填充数据后,您无法更改DataType.但是,您可以克隆Data表,更改列类型并将数据从先前的数据表加载到克隆表,如下所示.

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

  • DataTable.ImportRow()(或者说它的底层存储)通过使用 IConvertible 接口来转换值。确保相应地设置属性 DataTable.Locale!(默认为 CultureInfo.CurrentCulture) (3认同)
  • 这不起作用。我正在尝试创建一个内存流列而不是 db 即将到来的字节数组列。它给出 System.ArgumentException: Type of value has an mismatch with column typeCouldn't store <System.Byte[]> in DATA Column。预期类型是 MemoryStream (2认同)

rsb*_*rro 26

虽然在DataTable填充后您无法更改列的类型FillSchema,但您可以在通话后但在通话之前更改它Fill.例如,假设第三列是你想从转换的一个doubleInt32,你可以使用:

adapter.FillSchema(table, SchemaType.Source);
table.Columns[2].DataType = typeof (Int32);
adapter.Fill(table);
Run Code Online (Sandbox Code Playgroud)


小智 17

旧帖子,但我想我已经权衡了一个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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后可以像这样调用它:

MyTable.ConvertColumnType("MyColumnName", typeof(int));
Run Code Online (Sandbox Code Playgroud)

当然使用您想要的任何类型,只要列中的每个值实际上都可以转换为新类型.

  • 我认为这是最优雅的解决方案,只需避免转换DBNull,例如`dr [dc.ColumnName] = dr [columnName] == DBNull.Value吗?DBNull.Value:Convert.ChangeType(dr [columnName],newType);` (3认同)

tsi*_*ilb 8

考虑也改变返回类型:

select cast(columnName as int) columnName from table
Run Code Online (Sandbox Code Playgroud)


小智 8

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)
Run Code Online (Sandbox Code Playgroud)


小智 8

我采取了一些不同的方法.我需要从OA日期格式的excel导入中解析日期时间.这种方法很简单,可以从......本质上构建,

  1. 添加所需类型的列
  2. 翻录转换值的行
  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;
        }
    
    Run Code Online (Sandbox Code Playgroud)


Jos*_*arl 5

一旦DataTable填充了a,您就无法更改列的类型。

在这种情况下,最好的选择是在填充之前添加​​一Int32列:DataTable

dataTable = new DataTable("Contact");
dataColumn = new DataColumn("Id");
dataColumn.DataType = typeof(Int32);
dataTable.Columns.Add(dataColumn);
Run Code Online (Sandbox Code Playgroud)

然后您可以将原始表中的数据克隆到新表中:

DataTable dataTableClone = dataTable.Clone();
Run Code Online (Sandbox Code Playgroud)

这是一篇包含更多详细信息的帖子


meh*_*hdi 5

如果您只想更改一列。例如从 string 更改为 int32 您可以使用 Expression 属性:

DataColumn col = new DataColumn("col_int" , typeof(int));
table.Columns.Add(col);
col.Expression = "table_exist_col_string"; // digit string convert to int  
Run Code Online (Sandbox Code Playgroud)


Mar*_*oth 5

我将 Mark 解决方案的效率(因此我不必使用.Clone整个 DataTable)与泛型和可扩展性相结合,因此我可以定义自己的转换函数。这就是我最终得到的结果:

/// <summary>
///     Converts a column in a DataTable to another type using a user-defined converter function.
/// </summary>
/// <param name="dt">The source table.</param>
/// <param name="columnName">The name of the column to convert.</param>
/// <param name="valueConverter">Converter function that converts existing values to the new type.</param>
/// <typeparam name="TTargetType">The target column type.</typeparam>
public static void ConvertColumnTypeTo<TTargetType>(this DataTable dt, string columnName, Func<object, TTargetType> valueConverter)
{
    var newType = typeof(TTargetType);

    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] = valueConverter(dr[columnName]);
    }

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

    // Give the new column the old column's name
    dc.ColumnName = columnName;
}
Run Code Online (Sandbox Code Playgroud)

这样,用法就更加简单,同时也可以自定义:

DataTable someDt = CreateSomeDataTable();
// Assume ColumnName is an int column which we want to convert to a string one.
someDt.ConvertColumnTypeTo<string>('ColumnName', raw => raw.ToString());
Run Code Online (Sandbox Code Playgroud)