LINQ - DataTable 與 List<TResult> 轉換

摘要:LINQ - DataTable 與 List 轉換

這段時間很緩慢的持續看著 LINQ 的書籍,腦袋轉了一下覺得似乎沒有寫過 DataTable 轉 List<TResult>,或者是 List<TResult> 轉 DataTable 的轉換。若能寫出來的話,或許對日後自己所負責的專案有所幫助吧。其實實作後您就會發現,都是在玩「反映 (Reflection)」,以下就來看看唄...

步驟一:建立一個新的專案後,隨後在建立一個名為「DataTableAndListExtensions.cs」Class


步驟二:撰寫 DataTable To List<TResult> 與 List<TResult> To DataTable 的程式碼

Code:

using System.Data;
using System.Reflection;
using System.Collections;

namespace DataTableAndListInterchangeSample
{
    public static class DataTableAndListExtensions
    {
        public static DataTable ListToDataTable<TResult>(this IEnumerable<TResult> ListValue) where TResult : class, new()
        {
            //建立一個回傳用的 DataTable
            DataTable dt = new DataTable();

            //取得映射型別
            Type type = typeof(TResult);

            //宣告一個 PropertyInfo 陣列,來接取 Type 所有的共用屬性
            PropertyInfo[] PI_List = null;

            foreach (var item in ListValue)
            {
                //判斷 DataTable 是否已經定義欄位名稱與型態
                if (dt.Columns.Count == 0)
                {
                    //取得 Type 所有的共用屬性
                    PI_List = item.GetType().GetProperties();

                    //將 List 中的 名稱 與 型別,定義 DataTable 中的欄位 名稱 與 型別
                    foreach (var item1 in PI_List)
                    {
                        dt.Columns.Add(item1.Name, item1.PropertyType);
                    }
                }

                //在 DataTable 中建立一個新的列
                DataRow dr = dt.NewRow();

                //將資料足筆新增到 DataTable 中
                foreach (var item2 in PI_List)
                {
                    dr[item2.Name] = item2.GetValue(item, null);
                }

                dt.Rows.Add(dr);
            }

            dt.AcceptChanges();

            return dt;
        }

        public static List<TResult> DataTableToList<TResult>(this DataTable DataTableValue) where TResult : class, new()
        {
            //建立一個回傳用的 List<TResult>
            List<TResult> Result_List = new List<TResult>();

            //取得映射型別
            Type type = typeof(TResult);

            //儲存 DataTable 的欄位名稱
            List<PropertyInfo> pr_List = new List<PropertyInfo>();

            foreach (PropertyInfo item in type.GetProperties())
            {
                if (DataTableValue.Columns.IndexOf(item.Name) != -1)
                    pr_List.Add(item);               
            }

            //足筆將 DataTable 的值新增到 List<TResult> 中
            foreach (DataRow item in DataTableValue.Rows)
            {
                TResult tr = new TResult();

                foreach (PropertyInfo item1 in pr_List)
                {
                    if (item[item1.Name] != DBNull.Value)
                        item1.SetValue(tr, item[item1.Name], null);
                }

                Result_List.Add(tr);
            }

            return Result_List;
        }
    }
}

步驟三:在 WinForm 當中驗證

Code:

namespace DataTableAndListInterchangeSample
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public class TestClass
        {
            public string uName { get; set; }
            public DateTime uDateTime { get; set; }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            List<TestClass> DataList = new List<TestClass>()
            {
                new TestClass
                {
                    uName = "Danny",
                    uDateTime = DateTime.Now
                },
                new TestClass
                {
                    uName = "Peggy",
                    uDateTime = DateTime.Now.AddDays(1)
                }
            };

            DataTable dt = DataList.ListToDataTable<TestClass>();

            string f_str = string.Empty;

            for (int i = 0; i < dt.Rows.Count; i++)
            {
                for (int j = 0; j < dt.Columns.Count; j++)
                {
                    if (string.IsNullOrEmpty(f_str))
                        f_str = dt.Rows[i][j].ToString();
                    else
                        f_str += "\r\n" + dt.Rows[i][j].ToString();
                }
            }

            MessageBox.Show(f_str, "系統:List To DataTable", MessageBoxButtons.OK, MessageBoxIcon.Information);

            f_str = string.Empty;

            List<TestClass> aaa = dt.DataTableToList<TestClass>();

            foreach (var item in aaa)
            {
                f_str += item.uName + "\r\n" + item.uDateTime + "\r\n";
            }

            MessageBox.Show(f_str, "系統:DataTable To List", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
    }
}

結果:



參考:
Linq:轉換成 DataTable
擴展方法(1) DataTable 和List 相互轉換
反映 (C# 程式設計手冊)
Reflection in C#
Reflection技術應用