【问题标题】:Joining datatables dynamic动态连接数据表
【发布时间】:2020-09-26 03:01:51
【问题描述】:

我正在努力解决以下问题:

我有一个数据表,其中包含从 SQL Server 数据库中检索到的信息。检索到的信息与某些产品的价格有关。因此,例如,数据表具有特定价目表上特定产品的价格。一种产品可能出现在几个不同的价目表中,而今天在数据表上,每个组合都是不同的行。例如:

我需要将数据表转换为每个产品只有一行的数据表,并且价格表信息在列上:

示例数据:

几点说明:

我不知道我会有多少个价目表,所以我可以将“成本”列(例如)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
                          };



        }
  1. 我应该通过这种方法继续前进吗?我没有得到一个扁平化的结果,我不知道如何解决这个问题。
  2. 我可以访问数据库,因此我可能会更改查询。
  3. 数据透视表可以用吗?

非常感谢!

【问题讨论】:

  • 一般来说,使用DataTable 不是现代方法,但有时它是最简单的。您的示例数据似乎与您的 PRODUCT/PRICELIST/PRICE 图片无关 - 对吗?
  • PS 注意这总是浪费:DataSet dataSetsingle = new DataSet(); dataSetsingle =:你刚刚创建了一个新的DataSet,然后用一个作业覆盖了它,把它扔掉了。不要那样做。

标签: c# linq .net-core datatable


【解决方案1】:

如果您想继续使用 LINQ join 而不是 DataTables,此扩展方法会有所帮助,但我认为您最好使用支点。不幸的是,我无法从您的问题中判断出您想要旋转什么,但我也有一个 DataTable 的旋转方法。

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;
    }

}

嗯...没有意识到代码使用了多少扩展方法:)

【讨论】:

    猜你喜欢
    • 2013-10-31
    • 2012-02-27
    • 1970-01-01
    • 1970-01-01
    • 2015-08-09
    • 2010-12-25
    • 2016-07-05
    • 2013-10-09
    • 2012-04-01
    相关资源
    最近更新 更多