在将List 转换为DataTable时,从类中添加选择属性

问题描述 投票:0回答:2

我正在尝试将列表转换为数据表。我已经完成了基本轮廓,但是只停留在一部分上。我试图只从类中获取一些属性。

public static DataTable ToDataTable<T>(this IList<T> data)
{
    PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
    DataTable table = new DataTable();

    table.Columns.Add("type", typeof(string));
    table.Columns.Add("id", typeof(Int32));
    table.Columns.Add("name", typeof(string));
    table.Columns.Add("city", typeof(string));

    foreach (T item in data)
    {
        DataRow row = table.NewRow();
        foreach (PropertyDescriptor prop in properties)
        {
            row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
        }
        table.Rows.Add(row);
    }
    return table;
}

问题是,当到达第二个属性时,它抛出错误,指出列'unincludedCol'不属于表。

我该如何解决?

c#
2个回答
2
投票

如果只需要类型,ID,名称和城市,则可以将它们添加到字符串列表中:

List<string> columnNames = new List<string>
{
  "type","id","name","city"
};

或从dataTable中提取它们,如:

List<string> columnNames = new List<string>();

foreach(DataColumn column in dataTable.Columns)
{
    columnNames.Add(column.ColumnName);
}

并在循环中检查columnNames是否包含prop.Name,例如:

foreach (T item in data)
{
    DataRow row = table.NewRow();
    foreach (PropertyDescriptor prop in properties)
    {
        if(!columnNames.Contains(prop.Name))
            continue;

        row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
    }

    table.Rows.Add(row);
}

注:代替if(!columnNames.Contains(prop.Name)),可以使用.Any()Equals方法忽略大小写:

if (!columnNames.Any(c => c.Equals(prop.Name, StringComparison.OrdinalIgnoreCase)))
    continue;

希望您能找到帮助。


0
投票

我相信使用属性是属性会更通用

[Attribute

[AttributeUsage(AttributeTargets.Property)]
public class UseAsTableColumn : Attribute
{
}

助手-更改了您的方法(使用属性名称作为列名称)

public static class Helper
{
    public static DataTable ToDataTable<T>(this IList<T> data)
    {
        var mappableAttrirbs = typeof(T).GetProperties().Where(x => x.GetCustomAttributes(typeof(UseAsTableColumn), true).FirstOrDefault() != null);
        DataTable table = new DataTable();

        foreach (var property in mappableAttrirbs)
        {
            table.Columns.Add(property.Name, property.PropertyType);
        }

        foreach (T item in data)
        {
            DataRow row = table.NewRow();
            foreach (var prop in mappableAttrirbs)
            {
                row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
            }
            table.Rows.Add(row);
        }
        return table;
    }
}

数据模型(要序列化的标记属性)

public class DataModel
{
    [UseAsTableColumn]
    public string Type { get; set; }

    [UseAsTableColumn]
    public int Id { get; set; }

    [UseAsTableColumn]
    public string Name { get; set; }

    [UseAsTableColumn]
    public string City { get; set; }

    public string _InternalValue { get; private set; }
}

Runner

public class Program
{
    static void Main(string[] args)
    {
        List<DataModel> data = new List<DataModel>()
        {
            new DataModel() { Type="Magic", Id= 1, Name = "foo", City = "bar" },
            new DataModel() { Type="Magic", Id= 2, Name = "foo1", City = "bar1" }
        };


        Helper.ToDataTable(data);
        Console.ReadKey();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.