2017-08-22 10 views
0

Wenn wir ein DataView mit Sortierung für mehrere Spalten erstellen, müssen wir bei Verwendung von FindRows Werte für alle Spalten angeben.Generische hierarchische DataView-Klasse mit dynamischen Ebenen von Sortierschlüsseln

Beispiel, wenn ich:

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

Ich bin gezwungen, Werte für alle drei Spalten angeben, wenn FindRows verwenden.

Es ist nicht möglich, alle Zeilen für einen bestimmten Wert von Col1 und "beliebige" Werte für Col2 und Col3 abzurufen.

Dies ist in einer SortedList möglich, wo ich SortedList geschachtelt haben kann. Die SortedList der obersten Ebene hat also den Schlüssel als Col1 und den Wert als eine andere SortedList. Die SortedList der zweiten Ebene hat einen Schlüssel als Col2 und einen Wert als eine andere SortedList. Schließlich hat die SortedList der dritten Ebene den Schlüssel Col3 und die Verweise auf die DataRows.

eine solche SortedList verwenden, ist es möglich, Methoden zu schreiben, wie:

public DataRowView[] FindAny(object[] keys) 

wo, wenn die Schlüssel Array nur 1 Schlüssel enthält, kann der Code der zweiten Ebene SortedList aus der 1. Ebene SortedList für die finden Taste, und durchlaufen Sie dann die SortedList der 2. und 3. Ebene und geben Sie alle Zeilen zurück, die zum ersten Schlüssel gehören.

Meine Frage ist, ob jemand bereits eine solche SortedList Klasse geschrieben hat, die dynamische Anzahl von Schlüsseln nehmen kann und mit jeder DataTable/DataRow arbeiten kann.

Hinweis: 1. Diese Frage hat nichts mit Präsentationsschicht zu tun. Ich suche eine Hilfsklasse für die Datenverarbeitung, zum Beispiel für die Analyse großer Datenmengen in mehreren Excel-Tabellen. 2. Ich bin derzeit nicht auf der Suche nach einer LINQ-basierten Lösung. Ich werde in Zukunft zu LINQ migrieren.

Danke.

+0

Wenn Sie daran interessiert sind, dann 'System.Linq.Dynamic' (Nuget Bibliothek) kann die Frage auf der Hand lösen jetzt –

+0

können Sie pls die Linq-Code für meine zukünftige Referenz schreiben. Lassen Sie mich sehen, wie einfach es ist, zu migrieren – AllSolutions

+0

Überprüfen Sie die Lösung, unter der die RowFilter-Eigenschaft von DataView zum Filtern –

Antwort

0

Als ich Ihre Frage überprüft und bewertete die verfügbaren Details auf der C# - dataview-rowfilter, in meinem Verständnis ist es viel einfacher, Sie die Lösung mit den DataView, wie folgt zu bekommen. Sie können eine beliebige Kombination der Spalten in einer beliebigen Reihenfolge an die RowFilter liefern, und es funktioniert wie erwartet. Ich habe mit LinqPad entwickelt, haben Sie die Dump in Visual Studio ersetzen

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

verwenden RowFilter hat Leistungsprobleme – AllSolutions

+0

Für die Verwendung der 'System.Linq.Dynamic' oder' benutzerdefinierten Ausdruck Bäume' Sie müssen DataTable/DataView in IEnuemrable 'oder' IQueryable 'konvertieren, wenn das in Ordnung ist, kann ich den Code posten. Ausdrucksbäume können jede Art von Filterung durchführen. –

+0

Bitte posten Sie es. Lassen Sie mich sehen, ob das eine bessere Art ist, Dinge zu tun, als die Lösung, die ich gepostet habe. – AllSolutions

0

ich es geschafft, meine eigene generische Klasse zu schreiben, die eine hierarchische Ansicht der Daten implementiert. Verbesserungen sind willkommen.

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; 
    } 
}