0

我有一个这样的数据表

Name| Value
----|------
NA  |  VA
NB  |  VB
NC  |  VC1
NC  |  VC2
ND  |  VD1
ND  |  VD2

和这样的课

Class NVMapping {
  List<string> NC { get; set; }
  List<string> ND { get; set; }
  string NA { get; set; }
  string NB { get; set; }
}

如何使用 linq 或其他方式将数据表传输到这种类型?

我想我需要在这里强调一件事。这种映射在我的应用程序中会很多。

不知何故,我认为使用反射可以使这个函数通用来处理所有这些有点映射。

所以如果可能的话,我更喜欢使用反射来实现这一点的通用函数。

如果可能的话,将数据表转换为上述转换的对象会更好。

谢谢 !

4

2 回答 2

7

我可以建议编写一个使用反射的通用方法。以下方法使用反射从 DataTable 中的 DataRow(或类的 List<>,DataTable 中的每个 DataRow 中的一个)填充类的公共属性,其中 ColumnName 与类中公共属性的名称完全匹配(大小写-敏感的)。如果 DataTable 具有与类中的属性不匹配的额外列,则它们将被忽略。如果 DataTable 缺少与类属性匹配的列,则该属性将被忽略并保留该类型的默认值(因为它是一个属性)。

    public static IList<T> DatatableToClass<T>(DataTable Table) where T : class, new()
    {
        if (!Helper.IsValidDatatable(Table))
            返回新列表<T>();

        类型 classType = typeof(T);
        IList<PropertyInfo> propertyList = classType.GetProperties();

        // 参数类没有公共属性。
        if (propertyList.Count == 0)
            返回新列表<T>();

        List<string> columnNames = Table.Columns.Cast<DataColumn>().Select(column => column.ColumnName).ToList();

        列表<T> 结果 = 新列表<T>();
        尝试
        {
            foreach(Table.Rows 中的 DataRow 行)
            {
                T 类对象 = 新 T();
                foreach(propertyInfo 属性在 propertyList 中)
                {
                    if (property != null && property.CanWrite) // 确保属性不是只读的
                    {
                        if (columnNames.Contains(property.Name)) // 如果属性是列名
                        {
                            if (row[property.Name] != System.DBNull.Value) // 不要复制 DBNull
                            {
                                对象属性值 = System.Convert.ChangeType(
                                        行[属性.名称],
                                        property.PropertyType
                                    );
                                property.SetValue(classObject, propertyValue, null);
                            }
                        }
                    }
                }
                结果.添加(类对象);
            }
            返回结果;
        }
        抓住
        {
            返回新列表<T>();
        }
    }

如果您有兴趣采用另一种方式,并从类的公共属性中填写 DataTable,我将在我的 C# 博客CSharpProgramming.tips/Class-to-DataTable中介绍这一点以及更多内容

于 2015-01-14T15:01:15.220 回答
3

这里是:

IEnumerable<DataRow> rows = table.AsEnumerable();
string naValue = null;
var naRow = rows.FirstOrDefault(r => r.Field<string>("Name") == "NA");
if(naRow != null)
    naValue = naRow.Field<string>("Value");
string nbValue = null;
var nbRow = rows.FirstOrDefault(r => r.Field<string>("Name") == "NB");
if(nbRow != null)
    nbValue = nbRow.Field<string>("Value");
NVMapping map = new NVMapping {
    NC = rows.Where(r => r.Field<string>("Name") == "NC")
        .Select(r => r.Field<string>("Value")).ToList(),
    ND = rows.Where(r => r.Field<string>("Name") == "ND")
        .Select(r => r.Field<string>("Value")).ToList(),
    NA = naValue,
    NB = nbValue
};
于 2012-11-14T16:20:29.157 回答