C# 在多个条件下外部连接两个数据表

C# 在多个条件下外部连接两个数据表,c#,.net,linq,join,C#,.net,Linq,Join,我正在尝试使用基于多个条件的Linq连接两个数据表。我能够使用此帖子获得一个合并工作:。但是,该示例仅在一个主键上连接,我需要能够指定多个条件 DataTable1(代码中的table1) 数据表2(代码中的表2) 我希望输出如下所示: +-------------------------------------------------------------+ | CLIENT,USER_NAME,LAST_LOGIN_DT_TM,BIRTH_DT_TM, TOTAL_ORDERS | +--

我正在尝试使用基于多个条件的Linq连接两个数据表。我能够使用此帖子获得一个合并工作:。但是,该示例仅在一个主键上连接,我需要能够指定多个条件

DataTable1(代码中的table1)

数据表2(代码中的表2)

我希望输出如下所示:

+-------------------------------------------------------------+
| CLIENT,USER_NAME,LAST_LOGIN_DT_TM,BIRTH_DT_TM, TOTAL_ORDERS |
+-------------------------------------------------------------+
| CLIENT1, USER1, 1-30-2014, 5-5-1980, 1500                   |
| CLIENT1, USER2, 12-21-2014, 5-2-1990,                       |
| CLIENT2, USER2, 11-30-2014, 5-1-1950, 2500                  |
| CLIENT2, USER1, 12-15-2014, 1-1-1900,                       |
+-------------------------------------------------------------+
以下是我到目前为止的情况:

DataTable targetTable = table1.Clone();

var dt2Columns = table2.Columns
                       .OfType<DataColumn>()
                       .Select(dc => new DataColumn(dc.ColumnName, dc.DataType, dc.Expression, dc.ColumnMapping));
var dt2FinalColumns = from dc in dt2Columns.AsEnumerable()
                      where targetTable.Columns.Contains(dc.ColumnName) == false
                      select dc;
                      targetTable.Columns.AddRange(dt2FinalColumns.ToArray());

//  This only matches on USER_NAME now, how do I add in CLIENT?
var rowData = from row1 in table1.AsEnumerable()
              join row2 in table2.AsEnumerable()
              on row1.Field<string>("USER_NAME") equals row2.Field<string>("USER_NAME")
              select row1; 
// This gives me the matched rows in rowData, but I'm not sure how to join it with original table1
DataTable targetTable=table1.Clone();
var dt2Columns=表2.列
第()类
.Select(dc=>newdatacolumn(dc.ColumnName、dc.DataType、dc.Expression、dc.ColumnMapping));
var dt2FinalColumns=来自dt2Columns.AsEnumerable()中的dc
其中targetTable.Columns.Contains(dc.ColumnName)=false
选择dc;
targetTable.Columns.AddRange(dt2FinalColumns.ToArray());
//现在这只匹配用户名,如何添加到客户端?
var rowData=来自表1.AsEnumerable()中的行1
连接表2中的第2行。AsEnumerable()
第1行的字段(“用户名”)等于第2行的字段(“用户名”)
选择第1行;
//这为我提供了rowData中匹配的行,但我不确定如何将其与原始表1连接起来

要连接多个列,必须使用匿名类型:

from row1 in table1.AsEnumerable()
join row2 in table2.AsEnumerable() on
  new { userName = row1.Field<string>("USER_NAME"), client = row1.Field<string>("CLIENT") }
equals
  new { userName = row2.Field<string>("USER_NAME"), client = row2.Field<string>("CLIENT") }
select new {
    userName = row1.Field<string>("USER_NAME"),
    client = row1.Field<string>("CLIENT"),
    totalOrders = row2.Field<int>("TOTAL_ORDERS"),
    (...)
}
来自表1中第1行的
。可计算()
将表2中的行2联接起来。上的AsEnumerable()
新{userName=row1.Field(“用户名”),client=row1.Field(“客户端”)}
等于
新建{userName=row2.Field(“用户名”),client=row2.Field(“客户端”)}
选择新的{
userName=row1.Field(“用户名”),
client=row1.字段(“client”),
totalOrders=row2.字段(“总订单”),
(...)
}

要连接多个列,必须使用匿名类型:

from row1 in table1.AsEnumerable()
join row2 in table2.AsEnumerable() on
  new { userName = row1.Field<string>("USER_NAME"), client = row1.Field<string>("CLIENT") }
equals
  new { userName = row2.Field<string>("USER_NAME"), client = row2.Field<string>("CLIENT") }
select new {
    userName = row1.Field<string>("USER_NAME"),
    client = row1.Field<string>("CLIENT"),
    totalOrders = row2.Field<int>("TOTAL_ORDERS"),
    (...)
}
来自表1中第1行的
。可计算()
将表2中的行2联接起来。上的AsEnumerable()
新{userName=row1.Field(“用户名”),client=row1.Field(“客户端”)}
等于
新建{userName=row2.Field(“用户名”),client=row2.Field(“客户端”)}
选择新的{
userName=row1.Field(“用户名”),
client=row1.字段(“client”),
totalOrders=row2.字段(“总订单”),
(...)
}

您需要使用新的{Field1,Field2}使用匿名类型加入

IEnumerable<DataRow> rowData = from row1 in table1.AsEnumerable()
          join row2 in table2.AsEnumerable()
          on new { col1 = row1.Field<string>("USER_NAME"),  col2 = row1.Field<string>("SecondField") }  equals {col1 = row2.Field<string>("USER_NAME") , col2 = row2.Field<string>("SecondField") }
          select row1; 
IEnumerable rowData=来自表1中的第1行。AsEnumerable()
连接表2中的第2行。AsEnumerable()
在新的{col1=row1.Field(“用户名”),col2=row1.Field(“SecondField”)}上等于{col1=row2.Field(“用户名”),col2=row2.Field(“SecondField”)}
选择第1行;

您需要使用新的{Field1,Field2}使用匿名类型加入

IEnumerable<DataRow> rowData = from row1 in table1.AsEnumerable()
          join row2 in table2.AsEnumerable()
          on new { col1 = row1.Field<string>("USER_NAME"),  col2 = row1.Field<string>("SecondField") }  equals {col1 = row2.Field<string>("USER_NAME") , col2 = row2.Field<string>("SecondField") }
          select row1; 
IEnumerable rowData=来自表1中的第1行。AsEnumerable()
连接表2中的第2行。AsEnumerable()
在新的{col1=row1.Field(“用户名”),col2=row1.Field(“SecondField”)}上等于{col1=row2.Field(“用户名”),col2=row2.Field(“SecondField”)}
选择第1行;

无法编译。这不是正确的匿名类型声明,因为编译器将无法为您推断属性名。将不编译。这不是一个正确的匿名类型声明,因为编译器将无法为您推断属性名。这将负责匹配,并将两个匹配的行放入rowData中。在那之后,获得我想要的外部联接输出的最佳方法是什么?您可以投影到不同的匿名类型。更新了我的答案。如果在运行时之前我不知道每个数据表中的所有列怎么办?在我的真实场景中,表1大约有55列,表2大约有25列。我只知道每个表都有“CLIENT”和“USER_NAME”列。是的,我犯了一个错误,我的代码无法编译。但是,即使您的代码没有编译,您也缺少“Client”的引号:)@MarcinJuraszek sorry没有在我之前的评论中标记您。如果在运行时之前我不知道每个数据表中的列,有什么想法吗?我希望避免在我的代码中写出50多列。Thanks这会处理匹配并将两个匹配的行放入rowData。在那之后,获得我想要的外部联接输出的最佳方法是什么?您可以投影到不同的匿名类型。更新了我的答案。如果在运行时之前我不知道每个数据表中的所有列怎么办?在我的真实场景中,表1大约有55列,表2大约有25列。我只知道每个表都有“CLIENT”和“USER_NAME”列。是的,我犯了一个错误,我的代码无法编译。但是,即使您的代码没有编译,您也缺少“Client”的引号:)@MarcinJuraszek sorry没有在我之前的评论中标记您。如果在运行时之前我不知道每个数据表中的列,有什么想法吗?我希望避免在我的代码中写出50多列。谢谢