繁体   English   中英

C#更改数据表列数据类型

[英]C# Change DataTable Column DataType

我有几列的数据表。 列数是动态的,但它们都是字符串。 我需要将DataTable的列从字符串转换为DataType,这将是该列中所有行的最佳匹配。

例:

如果一列中的所有行都是数字,则将该列的数据类型更改为number; 或返回DateTime(如果值是日期); 否则保留为字符串。

如何才能做到这一点? 我了解我必须创建一个新的DataTable。

这是您尝试执行的非常冒险的操作。 您所需要的只是一个不可预测的值,并且会有一个例外,而且测试每个单元的值将非常昂贵。 不知道您要完成什么工作,我建议1.测试每列中的所有单元格,以了解您需要哪种类型(非常昂贵)2.创建每列中具有正确DataType的新DataTable,然后复制旧数据中的内容。 与测试相比,这将是闪电fas

这是我将如何做的概述。 基本上使用基本类型的TryParse方法来确定最高计数。 然后添加具有新类型的新列,并转换尽可能多的值。 无法转换的将保留为DBNull.Value。

public class TypeCount {
    public int IntCount;
    public int LongCount;
    public int DoubleCount;
    public int DecimalCount;
    public int DateCount;
    // etc;

    // provide your own logic to determine the best type
    public Type BestType {
        get {
            int[] counts = new int[] { IntCount, LongCount, DoubleCount, DecimalCount, DateCount };
            Type[] types = new Type[] { typeof(int), typeof(long), typeof(double), typeof(decimal), typeof(DateTime) };
            Type bt = typeof(String);
            int max = 0;
            for (int i = 0; i < counts.Length; i++) {
                if (counts[i] > max) {
                    bt = types[i];
                    max = counts[i];
                }
            }
            return bt;
        }
    }
}

public static void TryParse(String s, NumberStyles ns, DateTimeStyles dts, IFormatProvider fp, String[] dateFormats, TypeCount counts) {
    if (String.IsNullOrEmpty(s))
        return;

    long l;
    int i;
    double d;
    decimal m;

    // could test byte and short too if needed
    if (int.TryParse(s, ns, fp, out i)) {
        counts.IntCount++;
        counts.LongCount++; // if int parses, then long also parses
    }
    else if (long.TryParse(s, ns, fp, out l))
        counts.LongCount++;

    // etc.

    foreach (String f in dateFormats) {
        DateTime date;
        if (DateTime.TryParseExact(s, f, fp, dts, out date))
            counts.DateCount++;
    }
}

public static void ConvertColumns(DataTable table) {
    IFormatProvider fp = CultureInfo.InvariantCulture;
    NumberStyles ns = NumberStyles.Any;
    DateTimeStyles dts = DateTimeStyles.None;
    String[] dateFormats = new String[] { "yyyy-MM-dd", "MM/dd/yyyy" };

    for (int i = 0; i < table.Columns.Count; i++) {
        DataColumn col = table.Columns[i];
        if (col.DataType != typeof(String))
            continue;

        TypeCount counts = new TypeCount();
        for (int j = 0; j < table.Rows.Count; j++) {
            String s = table.Rows[j][col] as String;
            TryParse(s, ns, dts, fp, dateFormats, counts);
        }

        Type bestType = counts.BestType;
        DataColumn temp = null;
        if (bestType == typeof(int)) {
            temp = table.Columns.Add("temp", typeof(int));
            for (int j = 0; j < table.Rows.Count; j++) {
                int val = 0;
                String s = table.Rows[j][col] as String;
                if (int.TryParse(s, ns, fp, out val))
                    table.Rows[j][temp] = val;
            }
        }
        //else if (bestType == ...) {}

        if (temp != null) {
            temp.SetOrdinal(col.Ordinal);
            table.Columns.Remove(col);
            temp.ColumnName = col.ColumnName;
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM