繁体   English   中英

将数据表转换为 LINQ 匿名类型

[英]Convert DataTable to LINQ Anonymous Type

我想要一个函数,它接受一个数据表并返回一个列表(对象不是 DataRow)例如。

我知道我可以做到这一点(但这需要知道列名):

        // Datatable dt = Filled from a Database query & has 3 columns Code,Description & ShortCode

        List<object> rtn = new List<object>();

        var x = from vals in dt.Select()
                select new
                {
                    Code = vals["Code"],
                    Description = vals["Description"],
                    ShortCode = vals["ShortCode"],
                };
        rtn.AddRange(x)

        return  rtn;

我想要的是一个通用版本,这样我就可以传入任何数据表,它会根据数据表中的列名生成。

由于在编译时不知道属性名称,并且您希望将数据用于 JSON 序列化,因此您可以使用以下内容创建字典列表。 如果您使用 Newtonsoft JSON,则序列化负责将键值对转换为 JSON 对象格式。

IEnumerable<Dictionary<string,object>> result = dt.Select().Select(x => x.ItemArray.Select((a, i) => new { Name = dt.Columns[i].ColumnName, Value = a })
                                                                                   .ToDictionary(a => a.Name, a => a.Value));

为了动态创建属性以处理具有不同列集的不同数据表,我们可以使用System.Dynamic.ExpandoObject 它基本上实现了 IDictionary <string,object>。 可以轻松转换为 JSON 的格式。

        int colCount = dt.Columns.Count;
        foreach (DataRow dr in dt.Rows)
        {
            dynamic objExpando = new System.Dynamic.ExpandoObject();
            var obj = objExpando as IDictionary<string, object>;

            for (int i = 0; i < colCount; i++)
            {
                string key = dr.Table.Columns[i].ColumnName.ToString();
                string val = dr[key].ToString();

                obj[key] = val;
            }
            rtn.Add(obj);
        }         

        String json = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(rtn);

您可以使用以下通用函数:-

private static List<T> ConvertDataTable<T>(DataTable dt)  
{  
   List<T> data = newList<T>();  
   foreach (DataRowrow in dt.Rows)  
   {  
      Titem = GetItem<T>(row);  
      data.Add(item);  
   }  
   return data;  
}  

private static TGetItem<T>(DataRow dr)  
{  
   Type temp = typeof(T);  
   T obj =Activator.CreateInstance<T>();  
   foreach (DataColumncolumn in dr.Table.Columns)  
   {  
      foreach (PropertyInfopro in temp.GetProperties())  
      {  
         if (pro.Name == column.ColumnName)  
         pro.SetValue(obj,dr[column.ColumnName], null);  
         else  
         continue;  
      }  
   }  
   return obj;  
}  

请查看我的文章,其中有关于如何使用这种通用方法的完整演示。

这是原始问题:

// Datatable dt = Filled from a Database query & has 3 columns Code,Description & ShortCode



    List<object> rtn = new List<object>();

        var x = from vals in dt.Select()
                select new
                {
                    Code = vals["Code"],
                    Description = vals["Description"],
                    ShortCode = vals["ShortCode"],
                };
        rtn.AddRange(x)

        return  rtn;

只需替换为

List<object> rtn = JsonConvert.DeserializeObject<List<object>>(JsonConvert.SerializeObject(dt));

您将提供匿名对象作为参数并使用 json/xml 序列化:

protected static List<T> ToAnonymousCollection<T>(DataTable dt, T anonymousObject)
{
    List<DataColumn> dataColumns = dt.Columns.OfType<DataColumn>().ToList();

    return dt.Rows.OfType<DataRow>().Select(dr =>
    {
        Dictionary<string, object> dict = new Dictionary<string, object>();

        dataColumns.Each(dc => dict.Add(dc.ColumnName, dr[dc]));

        return JsonConvert.DeserializeAnonymousType(JsonConvert.SerializeObject(dict), anonymousObject);
    }).ToList();
}

用法:

var anonymousCollection = ToAnonymousCollection(dt, new { Code = [ColumnTypeValue, eg. 0], Description = [ColumnTypeValue, eg. string.Empty], ShortCode = Code=[ColumnTypeValue, eg. 0] })

暂无
暂无

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

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