当我们在多列上创建一个带有排序的DataView时,我们被迫在使用FindRows时指定所有列的值。
示例,如果我有:
dv1 = new DataView(tbl1, null, "Col1, Col2, Col3", DataViewRowState.CurrentRows);
使用FindRows时,我被迫为所有3列指定值。
无法检索Col1的特定值和Col2和Col3的“任何”值的所有行。
这在SortedList中是可能的,我可以在其中嵌套SortedList。因此,顶级SortedList将具有作为Col1的键,并将值作为另一个SortedList。第二级SortedList将具有作为Col2的键,并将值作为另一个SortedList。最后,第3级SortedList将具有作为Col3的键,以及对DataRows的引用。
使用这样的SortedList,可以编写方法,例如:
public DataRowView[] FindAny(object[] keys)
其中如果keys数组只包含1个键,则代码可以从键的第1级SortedList中找到第2级SortedList,然后遍历第2级和第3级SortedList并返回所有行,因为它们属于1st键。
我的问题是,是否有人已经编写了这样一个可以获取动态数量的密钥的SortedList类,并且可以使用任何DataTable / DataRow。
注意: 这个问题与表示层无关。我正在寻找一个数据处理辅助类,比如分析多个Excel工作表中的大量数据。 2.我目前不是在寻找基于LINQ的解决方案。我将来会迁移到LINQ。
感谢。
答案 0 :(得分:0)
我设法编写了自己的泛型类,它实现了数据的层次视图。欢迎改进。
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;
}
}