LINQ to DataSet

フィルタ

IEnumerable<DataRow> query =
    from rowA in tableA.AsEnumerable()
    where rowA.Field<int>("col1") < 10
    orderby rowA.Field<int>("col2") descending
    select rowA;

メソッド構文では、次のようにします。

IEnumerable<DataRow> enumA = tableA.AsEnumerable();

IEnumerable<DataRow> query1
    = enumA.Where(rowA => rowA.Field<int>("col1") < 10);

IEnumerable<DataRow> query2
    = query1.OrderByDescending(rowA => rowA.Field<int>("col2"));

Join()メソッドによる結合は、次のようにします。メソッド ベースのクエリ構文例:結合 (LINQ to DataSet) - ADO.NET | Microsoft Learn

IEnumerable<DataRow> enumA = tableA.AsEnumerable();
IEnumerable<DataRow> enumB = tableB.AsEnumerable();

var query = enumA.Join(
    enumB,
    rowA => rowA["id"],
    rowB => rowB["id"],
    (a, b) => new { RowA = a, RowB = b });

このとき戻り値の型を明示したいならば、それ用のクラスを定義します。

class MyDataRow
{
    public DataRow RowA { get; set; }
    public DataRow RowB { get; set; }
}

そしてEnumerable.Join()の第4引数でその型を指定します。なお、ここでオブジェクトの生成時に用いている構文は、オブジェクト初期化子です。

IEnumerable<MyDataRow> query = enumA.Join(
    enumB,
    rowA => rowA["id"],
    rowB => rowB["id"],
    (a, b) => new MyDataRow { RowA = a, RowB = b });

子テーブルの条件でフィルタ

子テーブルをjoinで結合した上で、その行の値を条件に選択します。c# - DataSet select parent rows where child rows contains x value - Stack Overflow

IEnumerable<DataRow> query =
    from rowA in tableA.AsEnumerable()
    join rowB in tableB.AsEnumerable() on rowA["id"] equals rowB["id"]
    where rowB.Field<int>("col1") > 10
    select rowA;

またはサブクエリ (sub-query) で選択します。複合 from 句 - from 句 - C# リファレンス | Microsoft Learn

IEnumerable<DataRow> query =
    from rowA in tableA.AsEnumerable()
    from rowB in rowA.GetChildRows(dataRelation)
    where rowB.Field<int>("col1") > 10
    select rowA;

またはDataRowの子の行で判定するメソッドを用意し、それをwhere句から呼び出します。

IEnumerable<DataRow> query =
    from rowA in tableA.AsEnumerable()
    where Method(rowA, "col1", 10)
    select rowA;

孫テーブルの条件でフィルタ

子テーブルをjoinで結合し、さらにそれで孫テーブルも同様に結合します。mysql - SQL query to select only grandchildren - Stack Overflow

IEnumerable<DataRow> query =
    from rowA in tableA.AsEnumerable()
    join rowB in tableB.AsEnumerable() on rowA["idA"] equals rowB["idA"]
    join rowC in tableC.AsEnumerable() on rowB["idB"] equals rowC["idB"]
    where rowC.Field<int>("col1") > 10
    select rowA;

並べ替え

orderby句で並べ替えられます。

DataViewオブジェクトの作成

LINQのクエリのAsDataView()から、DataViewを作成できます。DataView - Creating a DataView Object (LINQ to DataSet) | Microsoft Learn

public static System.Data.DataView AsDataView<T> (
    this System.Data.EnumerableRowCollection<T> source
    ) where T : System.Data.DataRow;
AsDataView<T>(EnumerableRowCollection<T>) - DataTableExtensions.AsDataView Method (System.Data) | Microsoft Learn

クエリにAsDataView()を適用するには、それがEnumerableRowCollection<T>である必要があります。もしそれがIEnumerable<T>ならばCopyToDataTable()でコピーを作成できますが、値がコピーされるため、それへの修正は元のTableへは反映されません。Binding to lists of DataRows – SLaks.Blog

public static System.Data.DataTable CopyToDataTable<T> (
    this System.Collections.Generic.IEnumerable<T> source
    ) where T : System.Data.DataRow;
CopyToDataTable<T>(IEnumerable<T>) - DataTableExtensions.CopyToDataTable Method (System.Data) | Microsoft Learn

またDataRelationが設定されているとき、CopyToDataTable()で作成されたDataTableに、それは含まれません。

クエリからのDataViewの作成が困難ならば、元のDataTableからDataViewを作成し、そのRowFilterプロパティで結果をフィルタします。

List<int> ids = new List<int>();
foreach (DataRow dataRow in query)
{
    ids.Add((int)dataRow["id"]);
}

DataView view = new DataView();
view.Table = dataTable;
view.RowFilter = String.Format("id IN ({0})", String.Join(",", ids));
Microsoft Learnから検索