C#
③大きなDataTableでWhereを多重に重ねると遅い
出典: C# DataTable を LINQ でフィルタ・GroupBy・分割する3パターン — ハマりポイント3つ—俺が踏んだやつ / ③大きなDataTableでWhereを多重に重ねると遅い
// ❌ NG:同じフィルタを2回評価する
var filtered = dt.AsEnumerable().Where(r => r.Field<int>("price")> 1000);
int count = filtered.Count(); // 1回目スキャン
int sum = filtered.Sum(r => r.Field<int>("price")); // 2回目スキャン
// ✅ OK:一度ToList()で固める
var filtered = dt.AsEnumerable()
.Where(r => r.Field<int>("price")> 1000)
.ToList(); //ここで1回だけ評価
int count = filtered.Count;
int sum = filtered.Sum(r => r.Field<int>("price"));
▸ この snippet は実行結果未収録
▸ 実行結果は未収録です
Source収録記事
この snippet は記事の「ハマりポイント3つ—俺が踏んだやつ / ③大きなDataTableでWhereを多重に重ねると遅い」セクションに登場する。コードの前後の文脈・ハマりどころの解説は記事本文で。
同じ記事から
10 件// ❌これは動かない var actives = dt.Where(r => r["IsActive"].ToString()== "1"); // ↑ 'DataTable'に'Where'の定義はない未収録
var actives = dt.Where(r => r["IsActive"].ToString()== "1");
#26dc8b3f4917
using System.Data; using System.Linq; // using System.Data.DataSetExtensions; // .NET Framework 4.0以降は標準で参照済みのはず未収録
前提:AsEnumerable()でIEnumerable化する
#a9874e6cceab
//価格1000以上、かつ"在庫あり"のフラグが立ってる行を抽出 var filtered = dt.AsEnumerable() .Where(r => r.Field<int>("price")>= 1000 && r.Field<bool>("in_stock"));
▶ 実行可
パターン1:フィルタ(Where)
#4d40bef0f3f9
//カテゴリ別の件数と合計金額 var summary = dt.AsEnumerable() .GroupBy(r => r.Field<string>("category")) .Select(g => new
▶ 実行可
パターン2: GroupBy +集計(Sum / Count / Average)
#4012f8c5d3ba
//価格1000以上の行だけ別DataTableに分割 var highPriceRows = dt.AsEnumerable() .Where(r => r.Field<int>("price")>= 1000);未収録
パターン3:分割(CopyToDataTable / ImportRow)
#59d35ff0dae0
DataTable dtCopy = dt.Clone(); //スキーマだけコピー foreach (var r in highPriceRows) { dtCopy.ImportRow(r);未収録
パターン3:分割(CopyToDataTable / ImportRow)
#7a058a47bdcf
