VB.net Linq在两列上进行连接

3
请帮助我。这是我的第一个LINQ。
我有两个数据表,需要在两个字段上进行连接。
我该如何做?
我尝试了以下代码但连接不起作用。 在 "yk.Field(Of String)("secNo")" 处出现错误,错误信息为 "Anonymous type member name can be inferred only from a simple or qualified name with no arguments"。
    Dim dtYk As DataTable = New DataTable("dtYk")
    dtYk.Columns.Add("secNo")
    dtYk.Columns.Add("BomLine")
    dtYk.Rows.Add("EA(1)", 1)
    dtYk.Rows.Add("EA(8)", 17)

    Dim dtIvt As DataTable = New DataTable("dtIvt")
    dtIvt.Columns.Add("secNo")
    dtIvt.Columns.Add("BomLine")
    dtIvt.Columns.Add("PartCode")
    dtIvt.Rows.Add("EA(1)", 1, "TRML07-32-LH-ASSY**")
    dtIvt.Rows.Add("EA(8)", 17, "328")

    ' Create a DataSet. Put both tables in it.
    Dim dsYk As DataSet = New DataSet("dsYk")
    dsYk.Tables.Add(dtYk)

    Dim dsIvt As DataSet = New DataSet("dsIvt")
    dsIvt.Tables.Add(dtIvt)

    Dim LinQuery = From yk In dtYk.AsEnumerable
                   Join ivt In dtIvt.AsEnumerable
                   On New With {yk.Field(Of String)("secNo") , yk.Field(Of String)("BomLine")} Equals New With {ivt.Field(Of String)("secNo") , ivt.Field(Of String)("BomLine")}
                   Select New With {yk.Field(Of String)("secNo") , yk.Field(Of String)("BomLine"),ivt.Field(Of String)("secNo")}

这是一个简单的版本,可以工作。但是它只在一个字段上进行连接,并且仅选择一个表。

Dim LinQuery = From yk In dtYk.AsEnumerable()
                       Join ivt In dtIvt.AsEnumerable()
                       On yk.Field(Of String)("secNo") Equals ivt.Field(Of String)("secNo")
                       Select yk

        Dim dt As New DataTable
        dt = LinQuery.CopyToDataTable

我的目标是在两个字段上进行连接,查询应该是yk.SecNo、yk.BomLine和ivt.PartCode。请帮忙。谢谢。

3个回答

2

使用 And 关键字连接复合主键应该可以工作(参考 MSDN文章,章节“通过使用复合键执行连接”)。快速测试演示如下:

Dim dtYk As New DataTable()
dtYk.Columns.Add("secNo")
dtYk.Columns.Add("BomLine")
dtYk.Rows.Add(1, 3)
dtYk.Rows.Add(2, 4)
dtYk.Rows.Add(3, 5)

Dim dtIvt As New DataTable
dtIvt.Columns.Add("secNo")
dtIvt.Columns.Add("BomLine")
dtIvt.Rows.Add(1, 3)
dtIvt.Rows.Add(2, 5)
dtIvt.Rows.Add(3, 4)
Dim LinQuery = From yk In dtYk.AsEnumerable
               Join ivt In dtIvt.AsEnumerable
               On yk.Field(Of String)("secNo") Equals ivt.Field(Of String)("secNo") And
                  yk.Field(Of String)("BomLine") Equals ivt.Field(Of String)("BomLine")
               Select New With {.secNo1 = yk.Field(Of String)("secNo"),
                                 .bomLine = yk.Field(Of String)("BomLine"),
                                 .bomLine2 = ivt.Field(Of String)("BomLine")}
For Each o As Object In LinQuery
    'the output is only one row :'
    '{ secNo1 = 1, bomLine = 3, bomLine2 = 3 }'
    Console.WriteLine(o)
Next

关于您收到的错误信息,这意味着您需要手动为匿名类型指定成员字段名称(在上面示例中的 Select 子句中也有演示)。

1

@har07表明您可以使用And来连接复合键,这是最好的答案,但是如果您想知道为什么匿名类型不起作用,您需要使用Key标记哪些属性用于相等性检查,否则它们将按引用进行比较。因此,以下方法也可以工作,但不如And版本易读。

Dim LinQuery =
    From yk In dtYk.AsEnumerable()
    Join ivt In dtIvt.AsEnumerable() On
        New With { Key .secNo = yk.Field(Of String)("secNo"), Key .BomLine = yk.Field(Of String)("BomLine") } _
        Equals _
        New With { Key .secNo = ivt.Field(Of String)("secNo"), Key .BomLine = ivt.Field(Of String)("BomLine") }
    Select New With {
        .secNo = yk.Field(Of String)("secNo"),
        .BomLine = yk.Field(Of String)("BomLine"),
        .PartCode = ivt.Field(Of String)("PartCode")
    }

0

类似的问题,参考VB.Net LINQ - 两个数据表之间的左外连接 - 限制为一行

忽略掉“限制为一行”的部分。

此外,您需要将以下代码作为JOIN操作的ON条件

On yk.Field(Of String)("secNo") Equals ivt.Field(Of String)("secNo") And yk.Field(Of String)("BomLine") Equals ivt.Field(Of String)("BomLine")


我尝试使用“on secno equals secno and bomline equals bomline”语法,但这不是LINQ的正确语法。我认为AND在JOIN中也是无效的。 - BobNoobGuy
所以在on语句中使用and时它无法编译?我还可以通过定义列类型来帮助linq。例如:Dim myCOl As New DataColumn("SecNo", System.Type.GetType("System.string")) dtYk.Columns.Add(myCOl) - user3910810

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接