我有一个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实现此转换?
谢谢!
答案 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的第一个参数选择键,第二个参数是值。然后很容易创建字典。分组g
是IEnumerable<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
语句。