将DataTable转换为LINQ匿名类型

时间:2015-02-24 07:55:29

标签: c# linq datatable

我想要一个接收数据表和功能的功能。返回一个List(对象不是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;

我想要的是通用版本,以便我可以传入任何数据表&amp;它将根据数据表中的列名生成。

5 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:3)

为了动态创建属性以便使用不同的Columns集处理不同的dataTable,我们可以使用System.Dynamic.ExpandoObject。它基本上实现了IDictionary&lt; string,object&gt;。格式,可以很容易地转换为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);

答案 2 :(得分:0)

您可以使用以下通用功能: -

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;  
}  

请查看 my article ,其中包含有关如何使用此通用方法的完整演示。

答案 3 :(得分:0)

这是原始问题:

// 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));

答案 4 :(得分:0)

您将具有提供匿名对象作为参数,并使用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] })