使用DataTable中的C#Linq的ToDictionary

时间:2012-02-04 23:47:54

标签: c# linq

我有一个SQL查询,我将其返回到DataTable:

SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, DATA_LENGTH 
FROM USER_TAB_COLUMNS
WHERE TABLE_NAME IN (SELECT DBTABLE FROM MY_APP_SETTINGS)

有了这个,我想创建一个Dictionary<string, List<ColumnInfo>>,其中键是TABLE_NAME,ColumnInfo是一个自定义类,其属性与查询中返回的其他三个字段相匹配。所以,我有:

IEnumerable<DataRow> rows = MyDataTable.Rows.Cast<DataRow>();
var ExistingColumns = MyDataTable.AsEnumerable().Select(dataRow => rows
    .Select(row => new { 
        Key = row["TABLE_NAME"], 
        Value = new ColumnInfo(){ 
            ColumnName = row["COLUMN_NAME"].ToString(), 
            DataType = row["DATA_TYPE"].ToString(), 
            DataLength = int.Parse(row["DATA_LENGTH"].ToString())
        }
    }).ToDictionary(data => data.Key, data => data.Value));

然而,这有两个问题:1)有重复的键,2)Value只是类的一个实例,而不是集合。

如何使用linq实现此转换?

谢谢!

3 个答案:

答案 0 :(得分:2)

ToDictionary()是一对一的。

一对多是ToLookup()具有相同的参数。

答案 1 :(得分:2)

首先,使用GroupBy按表名对行进行分组。这可确保表名称是唯一的。

IEnumerable<DataRow> rows = MyDataTable.Rows.Cast<DataRow>();
Dictionary<string, List<ColumnInfo>> ExistingColumns = rows
    .GroupBy(r => r["TABLE_NAME"].ToString(),
             r => new ColumnInfo {
                 ColumnName = r["COLUMN_NAME"].ToString(),
                 DataType = r["DATA_TYPE"].ToString(),
                 DataLength = Int32.Parse(r["DATA_LENGTH"].ToString())
             }
        )
    .ToDictionary(g => g.Key, g => g.ToList());

group by的第一个参数选择键,第二个参数是值。然后很容易创建字典。分组gIEnumerable<ColumnInfo>。因此,可以使用g.ToList()创建列表。

答案 2 :(得分:1)

GSerg建议使用ToLookup解决重复密钥问题。但是,要演示如何实现此目标并获取Dictionary,您需要先对表名进行分组,然后调用ToDictionary

var query = MyDataTable.AsEnumerable()
                       .GroupBy(row => row["TABLE_NAME"].ToString())
                       .ToDictionary(g => g.Key,
    g => g.Select(row => new ColumnInfo()
    { 
        ColumnName = row["COLUMN_NAME"].ToString(), 
        DataType = row["DATA_TYPE"].ToString(), 
        DataLength = int.Parse(row["DATA_LENGTH"].ToString())
    }));

这会返回Dictionary<string, IEnumerable<ColumnInfo>>。如果您需要列表,只需将ToList()附加到Select语句。