【问题标题】:DataTable Linq join many columnsDataTable Linq 连接多列
【发布时间】:2012-10-23 11:24:55
【问题描述】:

我在使用 Linq Join 时遇到问题。我想加入 2 个表,它们具有与 n 列相同的结构。我的问题是我不知道这些列的名称,那么如何在 select new 中重写它们?

表 1:这里我有一些 ID、Name 和 LastName 参数。注释、属性等为空

 ID    Name   LastName  Comment   Attribute ...     
                         "what"   "ABC"     ...
                         "hello"  "SDE"     ...
 3     lola               
 1              de           
 4     miki      
 ...   ...      ...      ...  

表 2:这里与表 1 相同,但在 Comment、Attribute 和 Rest 中有一些参数。

 ID    Name   LastName  Comment   Attribute ...
                        "what"   "ABC"     ...
                        "hello"  "SDE"     ...
 1              de       "hi"     
 4     miki                      "OKK"
 3     lola             "yo"     "LL"

结果:我想加入这样的表格

 ID    Name   LastName  Comment   Attribute ...
                        "what"   "ABC"     ...
                        "hello"  "SDE"     ...
 3     lola               "yo"    "LL" 
 1               de        "hi"   
 4     miki                       "OKK"
 ...   ...      ...      ...       ...     ...

我的代码是:

var Result= from tb1 in table1.AsEnumerable()
            join tb2 in tabl2.AsEnumerable()
            on new
            {                
             Name = tb1.Field<String>("Name"),
             LastName = tb1.Field<String>("LastName"),
             } equals new
            {
             Name=tb2.Field<String>("Name"),
             LastName=tb2.Field<String>("LastName"),
             }
            into grp1
            from tb3 in grp1.DefaultIfEmpty()
            select new
    {
     ID = tb1.Field<String>("ID"),
     Name = tb1.Field<String>("Name") ,
     LastName = tb1.Field<String>("LastName"),
     Comment = tb3!= null ? tb3.Field<String>("Comment") : null,
     Attribute= tb3!= null ? tb3.Field<String>("Attribute") : null,
     ...
     // Here should be next Columns Name but don't know how to put there

     };

我尝试了这段代码,但我的编译器只是挂了,不知道为什么

        for (int i = 2; i < table1.Rows.Count; i++)
        {
            foreach (DataRow dr in table2.Rows)
            {
                if ((table1.Rows[i]["Name"].ToString() == dr["Name"].ToString())&&table1.Rows[i]["LastName"].ToString() == dr["LastName"].ToString())
                {
                    table1.Rows.RemoveAt(i);
                    table1.ImportRow(dr);

                }
            }
        }
        dataGridView1.DataSource = table1;

【问题讨论】:

  • 我想我应该使用 ToDictonary 但不知道如何
  • 你为什么不直接返回 tb1 呢?而不是 'select new { ... }' 做 'select tb1' 之类的事情
  • 不,选择 tb1 在这里不会做任何事情。首先,我丢失了 table2 的结果,它什么也没显示
  • 只是一个问题,为什么需要合并它们? Table2 似乎包含整个 Table1?如果它对你有帮助,你可以看看这个问题stackoverflow.com/questions/725556/…。身份证呢,如果发生冲突,应该如何处理?数据冲突等。
  • 我想加入他们,因为我想拥有表 1 中的 ID、Name 和 LastName。在表 2 中,有时 ID、LastName、Name 可能会丢失。这就是我使用外左连接的原因

标签: c# linq join datatable


【解决方案1】:

对于table1中的每一个row1,如果table2中有匹配的row2,则使用row2。否则,使用第 1 行。

var newTable = table1.Clone();
foreach (DataRow row1 in table1.Rows) // To skip the first 2, use table1.Rows.Cast<DataRow>().Skip(2)
{
    var row = table2.Rows.Cast<DataRow>().FirstOrDefault(row2 => 
                row1["Name"].ToString() == row2["Name"].ToString() &&
                row1["LastName"].ToString() == row2["LastName"].ToString()) ?? row1;
    newTable.ImportRow(row);
}
dataGridView1.DataSource = newTable;

【讨论】:

  • 风险:我遇到错误无法将 [] 索引应用于表达式类型对象 row1
  • Risky:好的,我知道,我应该使用 var row1 而不是 DataRow row1,感谢 tousend more 的帮助...效果很好
【解决方案2】:

如何像您一样加入,然后将三个已知字段从 table1 的行复制到 table2 的行?

var copiedTable2 = table2.Copy(); // Copy table2 if you don't want it to be modified

var items = from tb1 in table1.AsEnumerable()
            join tb2 in copiedTable2.AsEnumerable()
            on new
            {                
                Name = tb1.Field<String>("Name"),
                LastName = tb1.Field<String>("LastName"),
            } equals new
            {
                Name=tb2.Field<String>("Name"),
                LastName=tb2.Field<String>("LastName"),
            }
            into grp1
            from tb3 in grp1.DefaultIfEmpty()
            select new
            {
                ID = tb1.Field<String>("ID"),
                Name = tb1.Field<String>("Name") ,
                LastName = tb1.Field<String>("LastName"),
                Row = tb3 ?? table2.NewRow();
            };

 foreach(var item in items)
 {
     item.Row.SetField<String>("ID", item.ID);
     item.Row.SetField<String>("Name", item.Name);
     item.Row.SetField<String>("LastName", item.LastName);
 }

 var rows = items.Select(x => x.Row);

 // How to set the rows as a DataGridView's DataSource
 var result = table2.Clone();
 foreach(var row in rows)
 {
     result.Rows.Add(row.ItemArray);
 }
 dataGridView.DataSource = result;

【讨论】:

  • 感谢 Risky,非常好的主意,但是如何在 DataGridView 中显示呢?我刚刚得到 ID、Name、LastName 和 Row Columns,其中 Row Column 具有 System.Data.Row 参数。我该如何扩展它?
  • @UniLe:您可以使用新的 DataRows 填充 DataTable 并将其分配给 DataGridView 的 DataSource。我不确定如何从 DataRow 创建匿名对象。
  • 风险:我收到错误此行已经属于另一个表。在 result.Rows.Add(row);
  • @UniLe:不客气!但是现在我想起来了,您的最新示例非常接近工作并且要短得多。我会努力让它发挥作用。
  • 为了减少重复我会做 var rows = item.Select(x=&gt;x.Row).Distinct(); 1 个问题,如果我在表 1 中有 1 个对象并尝试与表 2 绑定,它没有这个对象,它没有不出现,这是为什么呢?我可以转换你的代码,以便我得到左外连接吗?
【解决方案3】:

试试这个,不用循环

var resultTable = from tb1 in table1.AsEnumerable()
                   join tb2 in tabl2.AsEnumerable()
                   on tb1["Name"].ToString() equals tb2["Name"].ToString()
                   where tb1["LastName"].ToString() == tb2["LastName"].ToString()
                   select r;

 DataTable resultTable =result.CopyToDataTable();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-10
    相关资源
    最近更新 更多