概要
リフレクションを使用し、DataTable型 ⇔ List型の変換を行います。
変換クラスはチェーンで呼び出せるように、拡張メソッドとして実装しています。
環境
- Windows10
- .Net6
準備
エンティティクラスの定義
public class Item { public int Id { get; set; } public string Name { get; set; } public decimal Price { get; set; } }
サンプルデータの作成
static void Main(string[] args) { DataTable targetTable = new DataTable(); targetTable.Columns.Add("id", typeof(int)); targetTable.Columns.Add("name", typeof(string)); targetTable.Columns.Add("price", typeof(string)); for (int i = 0; i < 10; i++) { DataRow row = targetTable.NewRow(); row["id"] = i + 1; row["name"] = $"Item{i}番"; row["price"] = (i * 1000).ToString("#,##0"); targetTable.Rows.Add(row); } // DataTable -> List var list = targetTable.ToList<Item>(); // List -> DataTable var table2 = list.ToDataTable<Item>(); Console.ReadLine(); }
DataTable → List
public static IList<T> ToList<T>(this DataTable table) { var list = new List<T>(); foreach (DataRow row in table.Rows) { var item = Activator.CreateInstance<T>(); typeof(T).GetProperties().ToList().ForEach( //エンティティクラスの情報から型変換を行う(ex.カンマ付き文字列 -> Decimal) //p => p.SetValue(item, row[p.Name], p.PropertyType, null) p => p.SetValue(item, Convert.ChangeType(row[p.Name], p.PropertyType), null) ); list.Add(item); } return list; }
List → DataTable
/// <summary> /// List内のNullデータは考慮しない /// </summary> public static DataTable ToDataTable<T>(this IList<T> list) { var table = new DataTable(); typeof(T).GetProperties().ToList().ForEach( p => table.Columns.Add(p.Name, p.PropertyType) ); foreach (var item in list) { DataRow row = table.NewRow(); typeof(T).GetProperties().ToList().ForEach( p => row[p.Name] = p.GetValue(item, null) ); table.Rows.Add(row); } return table; }
List内にnullがあった場合どうするの?と言われた気がしたので、List内のnullデータをDBNullとして登録するパターンも作成します。
/// <summary> /// List内のNullデータをDBNull.Valueとして登録する /// </summary> public static DataTable ToDataTable2<T>(this IList<T> list) { var table = new DataTable(); typeof(T).GetProperties().ToList().ForEach( p => table.Columns.Add(p.Name, Nullable.GetUnderlyingType(p.PropertyType) ?? p.PropertyType) ); foreach (var item in list) { DataRow row = table.NewRow(); typeof(T).GetProperties().ToList().ForEach( p => row[p.Name] = p.GetValue(item) ?? DBNull.Value ); table.Rows.Add(row); } return table; }