您的位置:

DataTable转List完全指南

一、DataTable转List Json

DataTable是.NET中一个非常常用的数据类型。然而,当我们需要将DataTable转化成其他数据类型的时候,就需要考虑DataTable转化成List Json。下面我们就从以下几个方面来详细讲解如何完成转化过程。

1. 使用Json.net进行DataTable转换


using Newtonsoft.Json;
using System.Data;
using System.Web.Mvc;

public JsonResult GetJsonData()
{
    DataTable dt = GetDataTable(); //获取DataTable数据
    string json = JsonConvert.SerializeObject(dt); //DataTable转换成Json字符串
    return Json(json, JsonRequestBehavior.AllowGet); // "AllowGet" 这个参数允许 Get 方式的HTTP请求.
}

从上面的代码中可以看出,我们通过Json.net这个类库中的SerializeObject()函数,很容易地将DataTable转化成了Json格式的字符串。需要注意的是,一定要在Controller层的函数中将返回类型设置成JsonResult类型,否则会引发异常。

2. 使用JavaScriptSerializer进行DataTable转换


using System.Web.Script.Serialization;
using System.Data;
using System.Web.Mvc;

public JsonResult GetJsonData()
{
    DataTable dt = GetDataTable(); //获取DataTable数据
    JavaScriptSerializer js = new JavaScriptSerializer();
    string json = js.Serialize(dt); //DataTable转换成Json字符串
    return Json(json, JsonRequestBehavior.AllowGet); // "AllowGet" 这个参数允许 Get 方式的HTTP请求.
}

我们也可以使用.NET自带的JavaScriptSerializer进行DataTable转换,它与Json.net类库差不多,只是Transform DataTable to List Json过程多了一步,需要先实例化一个JavaScriptSerializer类。

3. 优化DataTable转Json的性能

为了提高DataTable转换成List Json的性能,我们可以使用异步的方式进行数据转换。下面是代码的实现:


public async Task<JsonResult> GetJsonData()
{
    DataTable dt = GetDataTable(); //获取DataTable数据
    string json = string.Empty;
    await Task.Factory.StartNew(() =>
    {
        json = JsonConvert.SerializeObject(dt); // DataTable转换成Json字符串
    });
    return Json(json, JsonRequestBehavior.AllowGet); // "AllowGet" 这个参数允许 Get 方式的HTTP请求.
}

通过在Controller层的函数中使用Task.Factory.StartNew()方法,我们就可以将数据转换和返回的Http响应分别挂起,从而达到提高程序性能的目的。

二、List转DataTable

除了将DataTable转成Json格式的字符串,还有一种常用的操作就是将List转成DataTable。那么,如何实现List转DataTable呢?下面我们就从以下几个方面详细介绍。

1. 将List元素插入到DataTable的行中


public static DataTable ToDataTable<T>(List<T> iList)
{
    DataTable dataTable = new DataTable();
    PropertyDescriptorCollection propertyDescriptorCollection = TypeDescriptor.GetProperties(typeof(T));
 
    for (int i = 0; i < propertyDescriptorCollection.Count; i++)
    {
        PropertyDescriptor propertyDescriptor = propertyDescriptorCollection[i];
        Type type = propertyDescriptor.PropertyType;
 
        if (type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable)))
        {
            type = Nullable.GetUnderlyingType(type);
        }
 
        dataTable.Columns.Add(propertyDescriptor.Name, type);
    }
 
    object[] values = new object[propertyDescriptorCollection.Count];
 
    foreach (T iListItem in iList)
    {
        for (int i = 0; i < values.Length; i++)
        {
            values[i] = propertyDescriptorCollection[i].GetValue(iListItem);
        }
 
        dataTable.Rows.Add(values);
    }
    return dataTable;
}

通过定义ToDataTable()函数,我们可以将List转成DataTable,并且在其中逐一遍历List中的元素,将其插入到DataTable的每一行中,从而得到我们需要的结果。

2. 将List元素的属性作为DataTable的列


public static DataTable ToDataTable<T>(this IList<T> data)
{
    PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
    DataTable table = new DataTable();
    for (int i = 0; i < props.Count; i++)
    {
        PropertyDescriptor prop = props[i];
        if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable)))
        {
            table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType));
        }
        else
        {
            table.Columns.Add(prop.Name, prop.PropertyType);
        }
    }
    object[] values = new object[props.Count];
    foreach (T item in data)
    {
        for (int i = 0; i < values.Length; i++)
        {
            values[i] = props[i].GetValue(item);
        }
        table.Rows.Add(values);
    }
    return table;
}

通过重载ToDataTable()函数,我们就可以将List中元素的属性名作为DataTable的列名。这种方法在将List转成DataTable时非常有用。

三、DataTable转成List

DataTable直接转为List是我们常用到的方式之一。下面我们就从以下几个方面详细介绍如何实现DataTable转List操作。

1. 遍历每一行数据转成List元素


public static List<T> ToList<T>(this DataTable table) where T : class, new()
{
    List<T> list = new List<T>();
    foreach (DataRow row in table.Rows)
    {
        T item = new T();
        foreach (DataColumn column in table.Columns)
        {
            PropertyInfo property = item.GetType().GetProperty(column.ColumnName);
            if (property != null && row[column] != DBNull.Value)
            {
                property.SetValue(item, row[column], null);
            }
        }
        list.Add(item);
    }
    return list;
}

将DataTable逐行遍历,将每一行数据转化成List元素,这是最为直接的方法。同时,在List中需要指定泛型参数类型T。

2. 使用Linq进行数据的筛选和过滤


public static List<T> ToList<T>(this DataTable table) where T : new()
{
    List<T> result = new List<T>();
    foreach (var row in table.AsEnumerable())
    {
        T item = new T();
        foreach (var prop in item.GetType().GetProperties())
        {
            try
            {
                PropertyInfo propertyInfo = item.GetType().GetProperty(prop.Name);
                object propertyValue = row[prop.Name];
                if (propertyValue == null)
                {
                    propertyValue = DBNull.Value;
                }
                propertyInfo.SetValue(item, propertyValue, null);
            }
            catch (Exception ex)
            {
                continue;
            }
        }
        result.Add(item);
    }
    return result;
}

我们还可以使用Linq进行筛选和过滤操作,将DataTable转换成指定泛型T的List。这种方式操作更为灵活,并可以直接通过Lambda表达式对数据进行操作。

四、DataTable转Sheet

DataTable转Sheet通常用于Excel表格的导出操作。下面我们就从以下几个方面详细介绍如何将DataTable转成Sheet。

1. 使用NPOI库转换成Sheet


using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using System.IO;

public ActionResult ExportExcel()
{
    DataTable dt = GetDataTable(); //获取DataTable数据
    HSSFWorkbook workbook = new HSSFWorkbook();
    ISheet sheet = workbook.CreateSheet("sheet1");
    IRow headerRow = sheet.CreateRow(0);
    for (int i = 0; i < dt.Columns.Count; i++)
        headerRow.CreateCell(i).SetCellValue(dt.Columns[i].ColumnName);
    for (int i = 0; i < dt.Rows.Count; i++)
    {
        IRow row = sheet.CreateRow(i + 1);
        for (int j = 0; j < dt.Columns.Count; j++)
            row.CreateCell(j).SetCellValue(dt.Rows[i][j].ToString());
    }
    MemoryStream ms = new MemoryStream();
    workbook.Write(ms);
    Response.BinaryWrite(ms.ToArray());
    Response.End();
    return View();
}

这里使用NPOI库来将DataTable转成Sheet,主要用到了HSSFWorkbook和ISheet两个类。NPOI库是.NET中操作Excel的最好选择之一。

2. 使用EPPlus库转换成Sheet


using OfficeOpenXml;
using System.Web.Mvc;
using System.IO;

public void ExportExcel()
{
    List<MyObj> myList = new List<MyObj>();
    DataTable dt = myList.ToDataTable();
    byte[] fileContents;
    using (var package = new ExcelPackage())
    {
        // Add a new worksheet to the empty workbook
        ExcelWorksheet worksheet = null;
        worksheet = package.Workbook.Worksheets.Add("sheet1");
        worksheet.Cells[1, 1].LoadFromDataTable(dt, true);
        fileContents = package.GetAsByteArray();
    }
    Response.ContentType = "application/vnd.ms-excel";
    Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}", "MyExcel.xlsx"));
    Response.OutputStream.Write(fileContents, 0, fileContents.Length);
    Response.OutputStream.Flush();
    Response.OutputStream.Close();
    Response.End();
}

使用EPPlus库将DataTable转成Sheet非常方便。EPPlus基于Open XML标准,支持新的Excel格式,并且速度快,使用方便。

五、Dataframe转List

Dataframe是pandas库中的常用数据类型,通常需要将其转成List,以方便后续操作。以下是如何将Dataframe转成List的几种方法。

1. 使用values属性转换成List


import pandas as pd
import numpy as np

df = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), columns=['a', 'b', 'c'])

list1 = df.values.tolist()
print(list1)

使用pandas库中的values属性,可以将Dataframe转成List。Cpandas库的values属性是将值以数组形式返回,然后变成List。

2. 使用to_dict()方法将Dataframe转成List


import pandas as pd
import numpy as np

df = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), columns=['a', 'b', 'c'])

dict1 = df.to_dict('records')
print(dict1)

利用pandas库中的to_dict()方法,可以将Dataframe转成字典形式,然后再以字典形式返回List。

3. 合并列名和数据,并将Dataframe转为List


import pandas as pd
import numpy as np

df = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), columns=['a', 'b', 'c'])

result = []
for col in df.columns:
    values = df[col].values
    col_values = [{col: value} for value in values]
    for i in range(len(col_values)):
        if len(result) <= i:
            result.append({})
        result[i].update(col_values[i])

list1 = []
for item in result:
    row = []
    for col in df.columns:
        row.append(item[col])
    list1.append(row)

print(list1)

通过合并列名和数据两个属性,然后将Dataframe转化成List。这种方法较为麻烦,但是可以准确地实现Goal。

六、DataTable转String

将DataTable转成String,是我们在后端计算和前端展示时常用的操作。下面我们就从如下几个方面详细讲解如何将DataTable转成String。

1. 拼接字符串输出


private static string DataTable2String(DataTable dt)
{
    string result = string.Empty;
    for (int i = 0; i < dt.Rows.Count; i++)
    {
        result += dt.Rows[i]["ColumnName