[英]Joining datatables dynamic
我正在努力解决以下问题:
我有一个数据表,其中包含从 SQL 服务器数据库检索到的信息。 检索到的信息与某些产品的价格有关。 因此,例如,数据表具有特定价目表上特定产品的价格。 一种产品可能出现在几个不同的价目表中,而今天在数据表上,每个组合都是不同的行。 例如:
我需要将数据表转换为每个产品只有一行的数据表,并且价目表信息在列上:
示例数据:
几点注意事项:
我不知道我会有多少价目表,所以我可以将“成本”列(例如)N 次。 需要包含产品信息(第一部分)。 每个 id_Art 不超过一行。
我一直在做以下工作,但我想退后一步,因为我可能会陷入困境,并且可能会有更简单的解决方案。
目前,我正在创建按每个价目表过滤的新数据表。 这背后的想法是加入数据表,但我被卡住了。
foreach(var pricelist in pricelists)
{
DataSet dataSetsingle = new DataSet();
dataSetsingle = GetDataSetForMultiTariff(tarifa, dpto, secc, fam, subfam); //This will return a datatable filtered by pricelist
System.Data.DataTable dtnew = dataSetsingle.Tables[0];
var results = from table1 in dtinitial.AsEnumerable()
join table2 in dtnew.AsEnumerable()
on new { A = table1["ID_ART"], B = table1["ID_FORMAT"] } equals new { A = table2["ID_ART"], B = table2["ID_FORMAT"] }
select new
{
table1,table2
};
}
非常感谢!
如果您想继续使用 LINQ join
DataTable
,这种扩展方法会有所帮助,但我认为使用 pivot 会更好。 不幸的是,我无法从您的问题中看出您想要 pivot 什么,但我也有用于DataTable
的 pivot 方法。
public static class DataTableExt {
// ***
// *** T Extensions
// ***
public static IEnumerable<T> AsSingleton<T>(this T first) {
yield return first;
}
// ***
// *** MemberInfo Extensions
// ***
public static Type GetMemberType(this MemberInfo member) {
switch (member) {
case FieldInfo mfi:
return mfi.FieldType;
case PropertyInfo mpi:
return mpi.PropertyType;
case EventInfo mei:
return mei.EventHandlerType;
default:
throw new ArgumentException("MemberInfo must be if type FieldInfo, PropertyInfo or EventInfo", nameof(member));
}
}
public static object GetValue(this MemberInfo member, object srcObject) {
switch (member) {
case FieldInfo mfi:
return mfi.GetValue(srcObject);
case PropertyInfo mpi:
return mpi.GetValue(srcObject);
case MethodInfo mi:
return mi.Invoke(srcObject, null);
default:
throw new ArgumentException("MemberInfo must be of type FieldInfo, PropertyInfo or MethodInfo", nameof(member));
}
}
public static T GetValue<T>(this MemberInfo member, object srcObject) => (T)member.GetValue(srcObject);
// ***
// *** Type Extensions
// ***
public static List<MemberInfo> GetPropertiesOrFields(this Type t, BindingFlags bf = BindingFlags.Public | BindingFlags.Instance) =>
t.GetMembers(bf).Where(mi => mi.MemberType == MemberTypes.Field || mi.MemberType == MemberTypes.Property).ToList();
// ***
// *** DataTable Extensions
// ***
public static IEnumerable<DataColumn> DataColumns(this DataTable aTable) => aTable.Columns.Cast<DataColumn>();
public static IEnumerable<string> ColumnNames(this DataTable aTable) => aTable.DataColumns().Select(dc => dc.ColumnName);
// Create new DataTable from LINQ join results on DataTable
// Expect T to be anonymous object of form new { [DataRow or other] d1, [DataRow or other] d2, ... }
public static DataTable FlattenToDataTable<T>(this IEnumerable<T> src) {
var res = new DataTable();
if (src.Any()) {
var firstRow = src.First();
var memberInfos = typeof(T).GetPropertiesOrFields();
var allDC = memberInfos.SelectMany(mi => (mi.GetMemberType() == typeof(DataRow)) ? mi.GetValue<DataRow>(firstRow).Table.DataColumns() : new DataColumn(mi.Name, mi.GetMemberType()).AsSingleton());
foreach (var dc in allDC) {
var newColumnName = dc.ColumnName;
if (res.ColumnNames().Contains(newColumnName)) {
var suffixNumber = 1;
while (res.ColumnNames().Contains($"{newColumnName}.{suffixNumber}"))
++suffixNumber;
newColumnName = $"{newColumnName}.{suffixNumber}";
}
res.Columns.Add(new DataColumn(newColumnName, dc.DataType));
}
foreach (var objRows in src)
res.Rows.Add(memberInfos.SelectMany(mi => (mi.GetMemberType() == typeof(DataRow)) ? mi.GetValue<DataRow>(objRows).ItemArray : mi.GetValue(objRows).AsSingleton()).ToArray());
}
return res;
}
}
嗯...没有意识到代码使用了多少扩展方法:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.