2017-08-22 15 views
0

複数の列に並べ替えを行ってDataViewを作成すると、FindRowsを使用するときにすべての列の値を指定する必要があります。動的レベルのソートキーを持つ汎用の階層型DataViewクラス

例、私が持っている場合:

dv1 = new DataView(tbl1, null, "Col1, Col2, Col3", DataViewRowState.CurrentRows); 

私はFindRowsを使用した場合、すべての3つの列の値を指定することを強制しています。

Col1の特定の値とCol2とCol3の「任意の」値のすべての行を取得することはできません。

これはSortedListで可能です。ここでは、SortedListをネストすることができます。したがって、最上位のSortedListは、Col1としてキーを持ち、別のSortedListとして値を持ちます。 2番目のレベルのSortedListは、Col2としてキーを持ち、別のSortedListとして値を持ちます。最後に、3番目のレベルのSortedListは、Col3としてのキーと、DataRowsへの参照を持ちます。そのようなSortedListのを使用

、同様に、メソッドを記述することが可能である:キー配列が1つのだけのキーが含まれている場合、コードは1番目レベルSortedListのから2番目のレベルのSortedListのを見つけることができる

public DataRowView[] FindAny(object[] keys) 

2番目と3番目のレベルのSortedListをループし、すべての行を1番目のキーに属するように戻します。

私の質問は誰もすでに、動的な数のキーを取り、任意のDataTable/DataRowで動作するSortedListクラスを作成しているかどうかです。

注: 1.この質問はプレゼンテーションレイヤとは関係ありません。私は、データ処理のためのヘルパークラスを探しています。たとえば、複数のExcelシートで大量のデータを分析する場合などです。 2.私は現在LINQベースのソリューションを探していません。私は将来LINQに移行します。

ありがとうございました。

+0

あなたが注目している場合は、 'System.Linq.Dynamic'(Nugetライブラリー)は、今手元に –

+0

をこの問題を解決することができ、あなたは私の今後の参考のためにLINQのコードを投稿することができますPLS。 – AllSolutions

+0

DataViewの 'RowFilter'プロパティを使用してフィルタリングを行うソリューションを確認してください –

答えて

0

ご質問内容を確認し、C# - dataview-rowfilterの詳細を評価したところ、DataViewRowFilterを以下のように使用して解決するほうがはるかに簡単です。 RowFilterに任意の組み合わせの列を任意の順序で供給することができ、期待どおりに機能します。私はLinqPadを使用して開発している、あなたは、私は、データの階層ビューを実装して自分のジェネリッククラスを書くために管理

void Main() 
{ 
    DataTable dt = new DataTable("dt"); 

    dt.Columns.Add("Id",typeof(int)); 
    dt.Columns.Add("Name",typeof(string)); 
    dt.Columns.Add("Address",typeof(string)); 
    dt.Columns.Add("Phone",typeof(string)); 

    DataRow dr = dt.NewRow(); 

    dr.SetField(0,1); 
    dr.SetField(1,"Simon"); 
    dr.SetField(2,"Fairfax"); 
    dr.SetField(3,"AAAAAAAAAA"); 

    dt.Rows.Add(dr); 

    dr = dt.NewRow(); 

    dr.SetField(0, 2); 
    dr.SetField(1, "Mary"); 
    dr.SetField(2, "Toronto"); 
    dr.SetField(3, "BBBBBBBBBBB"); 

    dt.Rows.Add(dr); 

    dr = dt.NewRow(); 

    dr.SetField(0, 3); 
    dr.SetField(1, "Kevin"); 
    dr.SetField(2, "Berkshire"); 
    dr.SetField(3, "zomzom"); 

    dt.Rows.Add(dr); 

    dt.DefaultView.RowFilter = "Id > 1 And Name Not Like 'K%'"; 

    dt.DefaultView.ToTable().Dump(); 

} 
+0

RowFilterにはパフォーマンスの問題があります – AllSolutions

+0

' System.Linq.Dynamic'または 'カスタム式のツリーDataTable/DataViewを 'IEnuemrable 'または 'IQueryable 'に変換する必要があります。コードを投稿することができればうれしいです。式ツリーは、あらゆる種類のフィルタリングを行うことができます。 –

+0

投稿してください。それが私が掲示した解決策よりも、より良いやり方であるかどうかを見てみましょう。 – AllSolutions

0

Visual StudioでDumpを交換する必要があります。これの改善は大歓迎です。

public class HDataView 
{ 
    private SortedList mapDataRows; 
    int numMapLevels; 

    public HDataView(DataTable tbl, string[] colNames) 
    { 
     object colVal = null; 
     string colName = ""; 
     SortedList currLvlMap = null, nextLvlMap = null; 
     DataRow dr1 = null; 
     ArrayList arlLastLvlData; 

     mapDataRows = new SortedList(); 
     numMapLevels = colNames.Length; 

     for (int i = 0; i < tbl.Rows.Count; i++) 
     { 
      dr1 = tbl.Rows[i]; 
      currLvlMap = mapDataRows; 
      for (int j = 0; j < colNames.Length; j++) 
      { 
       colName = colNames[j]; 
       colVal = dr1[colName]; 

       if (j == colNames.Length - 1) 
       { 
        arlLastLvlData = (ArrayList)currLvlMap[colVal]; 
        if (arlLastLvlData == null) 
        { 
         arlLastLvlData = new ArrayList(); 
         currLvlMap[colVal] = arlLastLvlData; 
        } 
        arlLastLvlData.Add(dr1); 
       } 
       else 
       { 
        nextLvlMap = (SortedList)currLvlMap[colVal]; 
        if (nextLvlMap == null) 
        { 
         nextLvlMap = new SortedList(); 
         currLvlMap[colVal] = nextLvlMap; 
        } 

        //For the next column, the current nextLvlMap will become the prevLvlMap 
        currLvlMap = nextLvlMap; 
       } 
      } 
     } 
    } 

    public ArrayList FindAnyRows(object[] keys) 
    { 
     object keyVal = ""; 
     ArrayList arlDataRows = null, arlCurrRows = null; 
     SortedList startLvlMap = null, currLvlMap = null, nextLvlMap = null; 
     int mapLevel = 1, startLevel = 0; 

     currLvlMap = mapDataRows; 
     mapLevel = 1; 
     for (int i = 0; i < keys.Length; i++) 
     { 
      keyVal = keys[i]; 

      if (currLvlMap == null) 
      { 
       break; 
      } 

      if (i == numMapLevels - 1) 
      { 
       arlDataRows = (ArrayList)currLvlMap[keyVal]; 
      } 
      else 
      { 
       nextLvlMap = (SortedList)currLvlMap[keyVal]; 
       currLvlMap = nextLvlMap; 
       mapLevel++; 
      } 
     } 

     if (arlDataRows == null) 
     { 
      arlDataRows = new ArrayList(); 
     } 

     if (keys.Length > 0 && keys.Length < numMapLevels) 
     { 
      if (currLvlMap != null) 
      { 
       startLvlMap = currLvlMap; 
       startLevel = mapLevel; 

       if (mapLevel == numMapLevels) 
       { 
        for (int j = 0; j < startLvlMap.Count; j++) 
        { 
         arlCurrRows = (ArrayList)startLvlMap.GetByIndex(j); 
         if (arlCurrRows != null) 
         { 
          arlDataRows.AddRange(arlCurrRows); 
         } 
        } 
       } 
       else 
       { 
        for (int i = 0; i < startLvlMap.Count; i++) 
        { 
         mapLevel = startLevel; 
         currLvlMap = startLvlMap; 

         //travel full depth of this map, for each element of this map 
         for (; mapLevel <= numMapLevels; mapLevel++) 
         { 
          if (mapLevel == numMapLevels) 
          { 
           for (int j = 0; j < currLvlMap.Count; j++) 
           { 
            arlCurrRows = (ArrayList)currLvlMap.GetByIndex(j); 
            if (arlCurrRows != null) 
            { 
             arlDataRows.AddRange(arlCurrRows); 
            } 
           } 
          } 
          else 
          { 
           //Next level of current element of the starting map 
           nextLvlMap = (SortedList)currLvlMap.GetByIndex(i); 
           currLvlMap = nextLvlMap; 
          } 
         } 
        } 
       } 
      } 
     } 

     return arlDataRows; 
    } 
} 
関連する問題