【问题标题】:Dynamic Data tables joining Using Linq使用 Linq 加入动态数据表
【发布时间】:2011-03-11 06:21:21
【问题描述】:

我有两个数据表,它们的列是动态的,并且它们都有一个公共列。 现在我想加入这两个表。 得到综合结果。

提前致谢。

【问题讨论】:

  • 当您说“具有动态列的数据表”时,您究竟是什么意思?它是无类型的DataTable,是ExpandoObjectDynamicObject 派生实例的列表,还是完全不同的东西?
  • 实际上一个存储过程会返回两个表,ID为,名称为两个表中的公共列。列数相同,但列名不同。我们需要将两个表合并

标签: linq datatable dynamic-data


【解决方案1】:

您好,您可能希望加入在运行时生成的两个数据表。看看这个链接。可能对你有用

Finding common columns from two datatable and using those for Join condition in LINQ

【讨论】:

    【解决方案2】:

    一种简单的方法是在表上使用 AsEnumerable() 并将它们连接到公共列数据上。

    假设您的表如下所示:[Table1] -> [ID] [Name] [Location] | [Table2] -> [ID] [Description] 和 ID 列具有相同的值

    
    DataTable table1 = new DataTable();
    table1.Columns.Add("ID", typeof(int));
    table1.Columns.Add("Name", typeof(string));
    table1.Columns.Add("Location", typeof(string));
    table1.Rows.Add(1, "Name1", "Location1");
    table1.Rows.Add(2, "Name2", "Location2");
    table1.Rows.Add(3, "Name3", "Location3");
    
    DataTable table2 = new DataTable();
    table2.Columns.Add("ID", typeof(int));
    table2.Columns.Add("Description", typeof(string));
    table2.Rows.Add(1, "Description1");
    table2.Rows.Add(2, "Description2");
    table2.Rows.Add(3, "Description3");
    

    然后你只需要加入 ID 列上的表并选择生成的数据集

    
    var joinedTables = from data1 in table1.AsEnumerable()
                       join data2 in table2.AsEnumerable() on data1.Field("ID") equals data2.Field("ID")
                       select new {  id= data1.Field("ID"), 
                         name = data1.Field("Name"), 
                         loc = data1.Field("Location"),
                         desc = data2.Field("Description")
                       }; 
    

    结果数据:

    id name  loc       desc
    1  Name1 Location1 Description1
    2  Name2 Location2 Description2
    3  Name3 Location3 Description3
    

    【讨论】:

    • 实际上我需要两个表中的所有列,并且只需要一个公共列。在 select 语句中,我不想在 select new {} 中提及特定列
    【解决方案3】:

    这并不容易,不使用ExpandoObject 更是如此,因为 LINQ 通常被调整为生成强类型对象,您需要在编译时了解其架构。我看到这种情况发生的一种方法是通过转换调用组合方法,该方法将生成一个动态对象,其中包含所有发现的字段的组合

    public ExpandoObject CombineMe(DataRow r1, DataRow r2) 
    {
        dynamic x = new ExpandoObject();
        x.ID = r1.Field<int>("ID");
        x.Name = r1.Field<string>("Name");
    
        // use Expando as dictionary
        IDictionary<String, Object> xd = (IDictionary<String, Object>)x;
    
        // enumerat both rows for all columns not ID and Name and add to Expando
        foreach (DataColumn c in r1.Table.Columns) 
            if (c.ColumnName != "ID" && c.ColumnName != "Name") 
                xd.Add(c.ColumnName, r1[c]);
        foreach (DataColumn c in r2.Table.Columns)
            if (c.ColumnName != "ID" && c.ColumnName != "Name")
                xd.Add(c.ColumnName, r2[c]);
        return x;
    }
    
    /// .... further down
    
    var p = from a in table1.AsEnumerable()
            join b in table2.AsEnumerable() on a.Field<int>("ID") equals b.Field<int>("ID")
            select CombineMe(a, b);
    

    linq 中的 select 并不完全像 SQL select,它只是为转换提供了一个占位符,无论是简单的、复杂的甚至是外部调用代码。

    注意:如果您不想使用动态,则可以通过首先枚举两个表中的所有列并创建第三个表来类似地制定解决方案。然后将 CombineMe 更改为生成 DataRow 而不是 ExpandoObject,最后枚举 p 并将其所有条目(DataRow 的组合实例)添加到结果表中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-24
      • 2021-06-22
      • 1970-01-01
      • 2020-03-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多