DataTableをDataTableでフィルタリング

■使用例
sourceTable を filterTable でフィルタリング(結合キーはともに actor_id )。
ただし、actor_id=9 の行はフィルターによってsourceTableから除外されない。

var destinationTable = DataTableFilter.Filter(sourceTable, filterTable, 
                         "actor_id", "actor_id", new object[] { 9 });

■出力結果
DataTableFilter.png

■コード

public class DataTableFilter
{
  /// <summary>
  /// DataTableをDataTableで絞り込み。
  /// </summary>
  /// <param name="source">対象データテーブル</param>
  /// <param name="filter">フィルターとして使用するDataTable</param>
  /// <param name="sourceColumnName">source側の結合キー名</param>
  /// <param name="filterColumnName">filter側の結合キー名</param>
  /// <param name="essentialValues">フィルターでも除外しない値のリスト</param>
  /// <returns></returns>
  public static DataTable Filter(
    DataTable source, 
    DataTable filter,
    string sourceColumnName, 
    string filterColumnName, 
    IEnumerable<object> essentialValues = null)
  {
    return Filter(source, filter.AsEnumerable(), 
      sourceColumnName, filterColumnName, essentialValues);
  }

  /// <summary>
  ///  DataTableをDataRowコレクションで絞り込み。
  /// </summary>
  /// <param name="source">対象データテーブル</param>
  /// <param name="filter">フィルターとして使用するDataRowコレクション</param>
  /// <param name="sourceColumnName">source側の結合キー名</param>
  /// <param name="filterColumnName">filter側の結合キー名</param>
  /// <param name="essentialValues">フィルターでも除外しない値のリスト</param>
  /// <returns>フィルター後のDataTable</returns>
  public static DataTable Filter(
    DataTable source, 
    IEnumerable<DataRow> filter, 
    string sourceColumnName, 
    string filterColumnName, 
    IEnumerable<object> essentialValues = null)
  {
    var tmpFilter = filter.Select(i => i[filterColumnName]);
    if (essentialValues != null)
    {
      tmpFilter = tmpFilter.Concat(essentialValues);
    }
    tmpFilter = tmpFilter.Distinct();
    var rows = source.AsEnumerable().Join(tmpFilter, 
      o => o[sourceColumnName], i => i, (o, i) => o);
    return Copy(rows, source);
  }

  static DataTable Copy(IEnumerable<DataRow> rows, DataTable source)
  {
    if (rows.Count() > 0)
    {
      return rows.CopyToDataTable();
    }
    else
    {
      return source.Clone();
    }
  }
}