将DataTable转换为LINQ匿名类型

6
我希望有一个函数能够接收一个DataTable并返回一个列表(对象不是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;

我需要一个通用版本,这样我就可以传入任何数据表格,它将根据数据表格中的列名生成相应内容。


取决于列。#Abdul Rehman Sayed - Shahzad Khan
2
那么这个方法有什么用呢?你会如何使用那个 List<object>?在我看来它没有任何用处。 - Sriram Sakthivel
我需要它为WCF生成JSON。(我的WCF方法返回List<object>),这将被.NET和非.NET客户端使用。@SriramSakthivel - Abdul Rehman Sayed
不确定为什么需要返回 List<Object>。如果可以返回 JSON 字符串,可以使用 此方法。然后,在另一端使用序列化器的 Parse 方法将其解析为 JSON 对象。 - Sriram Sakthivel
@SriramSakthivel 我使用List<object>,因为非 .NET 客户端(例如:html/ajax)将使用 JSON(如果我提供 List<object>,wcf 将为我完成这项工作),而 .NET 客户端(如 win forms)将受益于使用集合作为服务引用代理。我想要一个通用版本,因为我有大约 25 个以上的这样的方法,并且不想重复代码。 - Abdul Rehman Sayed
5个回答

9

由于属性名称在编译时不知道,而您希望将数据用于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));

这是一个完美的解决方案。向你致敬! - kexx

5
为了动态创建属性,以便对不同的数据表使用不同的列集合,我们可以使用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);

1
这是原始问题:
// 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));

1
您可以使用以下通用函数:-
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;  
}  

请查看我的文章,其中详细演示了如何使用这个通用方法。

2
这需要事先知道T的类型。在我的情况下,我想要一个匿名对象。 - Abdul Rehman Sayed

1
你需要将匿名对象作为参数提供,并使用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] })

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接