.net - 左排除加入在 vb.net 中使用 LINQ

标签 .net vb.net linq datatable

我有 2 个数据表:

TableA:

id | name | phone
-----------------
1  | Paul | 8523      
2  | John | 5217     
3  | Stan | 5021

TableB:

id
--
2
5

我想在它们之间做一个不包括连接的左:我想要一个 DataTable 对象,其中包含 TableA 的所有行,这些行在 TableB< 中有相应的 id.

我想要的结果是这样的:

id | name | phone
-----------------
1  | Paul | 8523
3  | Stan | 5021

我已经用 for 循环完成了这个,但我认为如果我使用 LINQ 会更简单。问题是我尝试过的所有方法都不起作用。

如何使用 LINQ 执行此操作?

for 循环的代码是这样的:

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    Dim table = LeftExcludingJoin()

    If table IsNot Nothing Then
        For Each row As DataRow In table.Rows
            Console.WriteLine(row.Item("id") & " - " & row.Item("name") & " - " & row.Item("phone"))
        Next
    End If

End Sub

Private Function LeftExcludingJoin() As DataTable
    Dim tableA As New DataTable
    tableA.Columns.Add("id")
    tableA.Columns.Add("name")
    tableA.Columns.Add("phone")

    Dim tableB As New DataTable
    tableB.Columns.Add("id")

    'Rows for tableA
    Dim rowA1 As DataRow = tableA.NewRow
    rowA1.Item("id") = 1
    rowA1.Item("name") = "Paul"
    rowA1.Item("phone") = 8523
    tableA.Rows.Add(rowA1)

    Dim rowA2 As DataRow = tableA.NewRow
    rowA2.Item("id") = 2
    rowA2.Item("name") = "John"
    rowA2.Item("phone") = 5217
    tableA.Rows.Add(rowA2)

    Dim rowA3 As DataRow = tableA.NewRow
    rowA3.Item("id") = 3
    rowA3.Item("name") = "Stan"
    rowA3.Item("phone") = 5021
    tableA.Rows.Add(rowA3)

    'Rows for tableB
    Dim rowB1 As DataRow = tableB.NewRow
    rowB1.Item("id") = 2
    tableB.Rows.Add(rowB1)

    Dim rowB2 As DataRow = tableB.NewRow
    rowB2.Item("id") = 5
    tableB.Rows.Add(rowB2)

    'Get rows in A which are not in B
    Dim tableResult = tableA.Clone

    If tableA IsNot Nothing Then
        If tableB IsNot Nothing Then
            For Each rowA As DataRow In tableA.Rows
                Dim coincidence As Boolean = False
                For Each rowB As DataRow In tableB.Rows
                    If rowA.Item("id") = rowB.Item("id") Then
                        coincidence = True
                        Exit For
                    End If
                Next
                If coincidence = False Then
                    Dim newResultRow As DataRow = tableResult.NewRow
                    newResultRow.Item("id") = rowA.Item("id")
                    newResultRow.Item("name") = rowA.Item("name")
                    newResultRow.Item("phone") = rowA.Item("phone")
                    tableResult.Rows.Add(newResultRow)
                End If
            Next
        Else
            'All tableA values are part of the result because tableB is Nothing.
            Return tableA
        End If
        Return tableResult
    Else
        Return Nothing
    End If
End Function

最佳答案

介绍,以简化程序(在其他情况下可能有用):

  • 明确定义 Columns 数据类型:

    tableA.Columns.Add("id", GetType(Integer))
    
  • 电话号码(代码)是一个字符串,而不是一个整数(也许 phone 只是一个例子,没关系):

    tableA.Columns.Add("phone", GetType(String))
    
  • 可以使用接受 paramarray as object() 的重载来添加行.它可以是值序列或 Object() 数组:

    tableA.Rows.Add(1, "Paul", "8523")
    

System.Data.DataSetExtensions.dll程序集包含扩展方法,允许使用 AsEnumerable() 将 LINQ 查询(在 IEnumerable<T> 集合上运行)应用于数据表扩展方法。
此程序集通常与 System.Data 一起包含在新项目中。集会。如果不存在,请添加项目引用。

之后,可以在 Where() 上使用通常的过滤条件( Any()All()IEnumerable(Of DataRow) 等) 扩展方法生成的对象。

可以使用 EnumerableRowCollection<TRow> 将查询的 IEnumerable 结果 ( CopyToDataTable() )转换到 DataTable 中扩展方法。

  • 我们想在第一个数据表中包含行 Where() id列不等于 Any() id第二个数据表的列并使用此过滤器创建一个新的数据表:
    (当然你可以构造一个过滤器,以不同的方式应用相同的条件)
Private Function LeftExcludingJoin() As DataTable
    Dim tableA As New DataTable("TableA")
    tableA.Columns.Add("id", GetType(Integer))
    tableA.Columns.Add("name", GetType(String))
    tableA.Columns.Add("phone", GetType(String))

    tableA.Rows.Add(1, "Paul", "8523")
    tableA.Rows.Add(2, "John", "5217")
    tableA.Rows.Add(3, "Stan", "5021")

    Dim tableB As New DataTable("TableB")
    tableB.Columns.Add("id", GetType(Integer))

    tableB.Rows.Add(2)
    tableB.Rows.Add(5)

    Dim rows = tableA.AsEnumerable().
        Where(Function(drA) Not tableB.AsEnumerable().
            Any(Function(drB) CInt(drB("id")) = CInt(drA("id"))))

    Return If(rows.Count() = 0, Nothing, rows.CopyToDataTable())
End Function

关于.net - 左排除加入在 vb.net 中使用 LINQ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64862710/

相关文章:

c# - 设计n层应用程序时的困惑

java - 跨平台源代码控制?

vb.net - 如何将 "System.Drawing.Image"带到 DIB

c# - 每个符号重复多少次

c# - 在不激活的情况下与表单交互

.net - 配置管理器对比属性构建

c# - 在 LINQ Select 期间访问递增整数

c# - C# 中异步委托(delegate)的 VB.NET 等效项是什么?

c# - 如何在不必生成所有类的情况下使用 Linq-to-SQL?

c# - 仅日期而非时间的 OrderBy 列表