You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中动态修改DataTable列数据类型的优化方案咨询

问题描述

我需要在C#中创建一个DataTable,该表会被三个不同的场景调用,唯一差异是attr_value列的数据类型需分别设置为DateTime、Decimal或string。希望避免编写三个重复的DataTable创建方法,不确定用if-else是否合适,求合理解决思路。

现有代码实现

public class AttributeValueInsertDate : EntityBase
{
    public static object ResolveRequest(AttributeValueList attributeValueList)
    {
        return new
        {
            dateValuesTVP = AttributeValue.CreateAttributeValueDataTable(attributeValueList)
        };
    }
}

public class AttributeValueInsertDecimal : EntityBase
{
    public static object ResolveRequest(AttributeValueList attributeValueList)
    {
        return new
        {
            decimalValuesTVP = AttributeValue.CreateAttributeValueDataTable(attributeValueList)
        };
    }
}

public class AttributeValueInsertText : EntityBase
{
    public static object ResolveRequest(AttributeValueList attributeValueList)
    {
        return new
        {
            textValuesTVP = AttributeValue.CreateAttributeValueDataTable(attributeValueList)
        };
    }
}

public class AttributeValue
{
    public static DataTable CreateAttributeValueDataTable(AttributeValueList attributeValueList)
    {
        var dataTable = new DataTable();
        dataTable.Columns.Add("attr_id", typeof(Int32));
        dataTable.Columns.Add("attr_value", typeof(DateTime));
        dataTable.Columns.Add("effective_date", typeof(DateTime));
        dataTable.Columns.Add("expiration_date", typeof(DateTime));
        dataTable.Columns.Add("last_updated_user", typeof(string));
        dataTable.Columns.Add("last_updated_date_time", typeof(DateTime));

        if (attributeValueList.Count > 0)
        {
            foreach (var item in attributeValueList)
            {
                DataRow dr = dataTable.NewRow();
                dr[0] = item.AttributeId;
                dr[1] = item.Value;
                dr[2] = item.EffectiveDate;
                dr[3] = item.ExpirationDate;
                dr[4] = item.LastUpdatedUser;
                dr[5] = item.LastUpdatedDate;

                dataTable.Rows.Add(dr);
            }
        }
        return dataTable;
    }
}
解决方案

推荐两种简洁且易扩展的实现方式,比if-else更符合开闭原则:

方式一:传入Type参数指定列类型

修改CreateAttributeValueDataTable方法,增加一个Type参数来指定attr_value的类型,同时处理值的类型转换:

public class AttributeValue
{
    public static DataTable CreateAttributeValueDataTable(AttributeValueList attributeValueList, Type attrValueType)
    {
        var dataTable = new DataTable();
        dataTable.Columns.Add("attr_id", typeof(Int32));
        dataTable.Columns.Add("attr_value", attrValueType);
        dataTable.Columns.Add("effective_date", typeof(DateTime));
        dataTable.Columns.Add("expiration_date", typeof(DateTime));
        dataTable.Columns.Add("last_updated_user", typeof(string));
        dataTable.Columns.Add("last_updated_date_time", typeof(DateTime));

        if (attributeValueList.Count > 0)
        {
            foreach (var item in attributeValueList)
            {
                DataRow dr = dataTable.NewRow();
                dr[0] = item.AttributeId;
                // 转换值到目标类型,可根据实际情况添加异常处理
                dr[1] = Convert.ChangeType(item.Value, attrValueType);
                dr[2] = item.EffectiveDate;
                dr[3] = item.ExpirationDate;
                dr[4] = item.LastUpdatedUser;
                dr[5] = item.LastUpdatedDate;

                dataTable.Rows.Add(dr);
            }
        }
        return dataTable;
    }
}

然后修改三个调用类的ResolveRequest方法,传入对应类型:

public class AttributeValueInsertDate : EntityBase
{
    public static object ResolveRequest(AttributeValueList attributeValueList)
    {
        return new
        {
            dateValuesTVP = AttributeValue.CreateAttributeValueDataTable(attributeValueList, typeof(DateTime))
        };
    }
}

public class AttributeValueInsertDecimal : EntityBase
{
    public static object ResolveRequest(AttributeValueList attributeValueList)
    {
        return new
        {
            decimalValuesTVP = AttributeValue.CreateAttributeValueDataTable(attributeValueList, typeof(Decimal))
        };
    }
}

public class AttributeValueInsertText : EntityBase
{
    public static object ResolveRequest(AttributeValueList attributeValueList)
    {
        return new
        {
            textValuesTVP = AttributeValue.CreateAttributeValueDataTable(attributeValueList, typeof(string))
        };
    }
}

方式二:使用泛型方法

通过泛型参数约束attr_value的类型,代码更简洁且具备编译时类型检查:

public class AttributeValue
{
    public static DataTable CreateAttributeValueDataTable<T>(AttributeValueList attributeValueList)
    {
        var dataTable = new DataTable();
        dataTable.Columns.Add("attr_id", typeof(Int32));
        dataTable.Columns.Add("attr_value", typeof(T));
        dataTable.Columns.Add("effective_date", typeof(DateTime));
        dataTable.Columns.Add("expiration_date", typeof(DateTime));
        dataTable.Columns.Add("last_updated_user", typeof(string));
        dataTable.Columns.Add("last_updated_date_time", typeof(DateTime));

        if (attributeValueList.Count > 0)
        {
            foreach (var item in attributeValueList)
            {
                DataRow dr = dataTable.NewRow();
                dr[0] = item.AttributeId;
                dr[1] = (T)Convert.ChangeType(item.Value, typeof(T));
                dr[2] = item.EffectiveDate;
                dr[3] = item.ExpirationDate;
                dr[4] = item.LastUpdatedUser;
                dr[5] = item.LastUpdatedDate;

                dataTable.Rows.Add(dr);
            }
        }
        return dataTable;
    }
}

调用时指定泛型类型:

public class AttributeValueInsertDate : EntityBase
{
    public static object ResolveRequest(AttributeValueList attributeValueList)
    {
        return new
        {
            dateValuesTVP = AttributeValue.CreateAttributeValueDataTable<DateTime>(attributeValueList)
        };
    }
}

public class AttributeValueInsertDecimal : EntityBase
{
    public static object ResolveRequest(AttributeValueList attributeValueList)
    {
        return new
        {
            decimalValuesTVP = AttributeValue.CreateAttributeValueDataTable<Decimal>(attributeValueList)
        };
    }
}

public class AttributeValueInsertText : EntityBase
{
    public static object ResolveRequest(AttributeValueList attributeValueList)
    {
        return new
        {
            textValuesTVP = AttributeValue.CreateAttributeValueDataTable<string>(attributeValueList)
        };
    }
}

补充说明

  • 两种方式都避免了重复代码,后续新增类型只需添加对应调用逻辑,无需修改DataTable创建方法本身;
  • 若item.Value的原始类型和目标类型转换存在风险,可在方法内添加try-catch或类型校验逻辑,避免运行时异常;
  • 不推荐用if-else:后续新增类型需修改方法内部判断逻辑,违反开闭原则,代码扩展性差。

内容的提问来源于stack exchange,提问作者Tom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 05:55:47