Motinami Tech Note

プログラミング関連の技術情報を発信しています。

【C#】DataTableとListの変換について

概要

リフレクションを使用し、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;
}

参考資料

learn.microsoft.com

learn.microsoft.com