如何在不对列进行硬编码的情况下在 LINQ 中转换数据
How to pivot data in LINQ without hard coding columns
我在 sql server
中有一个 table 像这样
CodeItemsRule Table
CodeID ItemID RuleID
00009 D1 2
00009 D2 2
00009 D3 1
00008 D1 3
00007 D3 1
00007 D4 1
00010 D3 2
00010 D1 1
00010 D2 1
我需要像这样在 LINQ
中转换这些数据。
CodeID D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 D14
00007 1 1
00009 2 2 1
下面给出的是我的代码,但它没有将其转换为数据透视格式。
List<CodeItemsRule> _CodeItemRules = new CodeItemsRuleRepository.GetAll();
var _GroupResult = _CodeItemRules.GroupBy(g => g.CodeID).Select(g => new
{
CodeID = g.Key,
ItemRulesList = g.ToDictionary(t => t.ItemID, t => t.RuleID)
}).ToList()
我通过修改 the link 中的详细信息为您简化了解决方案。
首先在静态class中创建一个扩展方法ToPivotTable
:
public static class PivotClass
{
public static DataTable ToPivotTable<T, TColumn, TRow, TData>(this IEnumerable<T> source,
Func<T, TColumn> columnSelector,
Expression<Func<T, TRow>> rowSelector,
Func<IEnumerable<T>, TData> dataSelector)
{
DataTable table = new DataTable();
var rowName = ((MemberExpression)rowSelector.Body).Member.Name;
table.Columns.Add(new DataColumn(rowName));
var columns = source.Select(columnSelector).Distinct();
foreach (var column in columns)
table.Columns.Add(new DataColumn(column.ToString()));
var rows = source.GroupBy(rowSelector.Compile())
.Select(rowGroup => new
{
Key = rowGroup.Key,
Values = columns.GroupJoin(
rowGroup,
c => c,
r => columnSelector(r),
(c, columnGroup) => dataSelector(columnGroup))
});
foreach (var row in rows)
{
var dataRow = table.NewRow();
var items = row.Values.Cast<object>().ToList();
items.Insert(0, row.Key);
dataRow.ItemArray = items.ToArray();
table.Rows.Add(dataRow);
}
return table;
}
}
然后,使用列表中的此扩展方法来获取您的枢轴 DataTable
,如下所述:
List<CodeItemsRule> _CodeItemRules = new List<CodeItemsRule>()
{
new CodeItemsRule()
{
CodeID="00009",
ItemID="D1",
RuleID=2
},new CodeItemsRule()
{
CodeID="00009",
ItemID="D2",
RuleID=2
},new CodeItemsRule()
{
CodeID="00009",
ItemID="D3",
RuleID=1
},new CodeItemsRule()
{
CodeID="00008",
ItemID="D1",
RuleID=3
},new CodeItemsRule()
{
CodeID="00007",
ItemID="D3",
RuleID=1
},new CodeItemsRule()
{
CodeID="00007",
ItemID="D4",
RuleID=1
},new CodeItemsRule()
{
CodeID="00010",
ItemID="D3",
RuleID=2
},new CodeItemsRule()
{
CodeID="00010",
ItemID="D1",
RuleID=1
},new CodeItemsRule()
{
CodeID="00010",
ItemID="D2",
RuleID=1
}
};
var pivotTable = _CodeItemRules.ToPivotTable(
item => item.ItemID,
item => item.CodeID,
items => items.Any() ? items.Sum(x => x.RuleID) : 0);
我在 sql server
中有一个 table 像这样
CodeItemsRule Table
CodeID ItemID RuleID
00009 D1 2
00009 D2 2
00009 D3 1
00008 D1 3
00007 D3 1
00007 D4 1
00010 D3 2
00010 D1 1
00010 D2 1
我需要像这样在 LINQ
中转换这些数据。
CodeID D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 D14
00007 1 1
00009 2 2 1
下面给出的是我的代码,但它没有将其转换为数据透视格式。
List<CodeItemsRule> _CodeItemRules = new CodeItemsRuleRepository.GetAll();
var _GroupResult = _CodeItemRules.GroupBy(g => g.CodeID).Select(g => new
{
CodeID = g.Key,
ItemRulesList = g.ToDictionary(t => t.ItemID, t => t.RuleID)
}).ToList()
我通过修改 the link 中的详细信息为您简化了解决方案。
首先在静态class中创建一个扩展方法ToPivotTable
:
public static class PivotClass
{
public static DataTable ToPivotTable<T, TColumn, TRow, TData>(this IEnumerable<T> source,
Func<T, TColumn> columnSelector,
Expression<Func<T, TRow>> rowSelector,
Func<IEnumerable<T>, TData> dataSelector)
{
DataTable table = new DataTable();
var rowName = ((MemberExpression)rowSelector.Body).Member.Name;
table.Columns.Add(new DataColumn(rowName));
var columns = source.Select(columnSelector).Distinct();
foreach (var column in columns)
table.Columns.Add(new DataColumn(column.ToString()));
var rows = source.GroupBy(rowSelector.Compile())
.Select(rowGroup => new
{
Key = rowGroup.Key,
Values = columns.GroupJoin(
rowGroup,
c => c,
r => columnSelector(r),
(c, columnGroup) => dataSelector(columnGroup))
});
foreach (var row in rows)
{
var dataRow = table.NewRow();
var items = row.Values.Cast<object>().ToList();
items.Insert(0, row.Key);
dataRow.ItemArray = items.ToArray();
table.Rows.Add(dataRow);
}
return table;
}
}
然后,使用列表中的此扩展方法来获取您的枢轴 DataTable
,如下所述:
List<CodeItemsRule> _CodeItemRules = new List<CodeItemsRule>()
{
new CodeItemsRule()
{
CodeID="00009",
ItemID="D1",
RuleID=2
},new CodeItemsRule()
{
CodeID="00009",
ItemID="D2",
RuleID=2
},new CodeItemsRule()
{
CodeID="00009",
ItemID="D3",
RuleID=1
},new CodeItemsRule()
{
CodeID="00008",
ItemID="D1",
RuleID=3
},new CodeItemsRule()
{
CodeID="00007",
ItemID="D3",
RuleID=1
},new CodeItemsRule()
{
CodeID="00007",
ItemID="D4",
RuleID=1
},new CodeItemsRule()
{
CodeID="00010",
ItemID="D3",
RuleID=2
},new CodeItemsRule()
{
CodeID="00010",
ItemID="D1",
RuleID=1
},new CodeItemsRule()
{
CodeID="00010",
ItemID="D2",
RuleID=1
}
};
var pivotTable = _CodeItemRules.ToPivotTable(
item => item.ItemID,
item => item.CodeID,
items => items.Any() ? items.Sum(x => x.RuleID) : 0);