Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vb.net 使用LINQ在DataTable中查找更新的行_Vb.net_Linq_Datatable - Fatal编程技术网

Vb.net 使用LINQ在DataTable中查找更新的行

Vb.net 使用LINQ在DataTable中查找更新的行,vb.net,linq,datatable,Vb.net,Linq,Datatable,我正在VB.NET中构建一个应用程序,将数据从一个数据库推送到另一个数据库。源数据库是SQL Server,目标数据库是MySQL 我要做的是首先为每个数据库中的每个表创建数据表,我使用这些表进行比较。我以这样的方式编写查询,以便源数据表和目标数据表包含完全相同的列和值,从而使比较更容易 应用程序的这一面工作得很好。接下来我要做的是通过查找不存在的PK来查找目标数据库中不存在的行。然后,我将这些新行毫无问题地插入到目标数据库中 问题 我现在需要做的是查找每个表中已更新的行,即与目标DataTab

我正在VB.NET中构建一个应用程序,将数据从一个数据库推送到另一个数据库。源数据库是SQL Server,目标数据库是MySQL

我要做的是首先为每个数据库中的每个表创建数据表,我使用这些表进行比较。我以这样的方式编写查询,以便源数据表和目标数据表包含完全相同的列和值,从而使比较更容易

应用程序的这一面工作得很好。接下来我要做的是通过查找不存在的PK来查找目标数据库中不存在的行。然后,我将这些新行毫无问题地插入到目标数据库中

问题

我现在需要做的是查找每个表中已更新的行,即与目标DataTable中的对应行不相同的行。我已尝试使用
Except()
,如下例所示:

Public Function GetUpdates(ByVal DSDataSet As MSSQLQuery, ByVal AADataSet As MySQLQuery, Optional ByVal PK As String = Nothing) As List(Of DataRow)
    ' Determines records to be updated in the AADB and returns list of new Rows
    ' Param DSDataSet - MSSQLQuery Object for source table
    ' Param AADataSet - MySQLQuery Object for destination table
    ' Optional Param PK - String of name common columns to treat as PK
    ' Returns List(Of DataRow) containing rows to update in table

    Dim orig = DSDataSet.GetDataset()
    Dim origTable = orig.Tables(0).AsEnumerable()
    Dim destination = AADataSet.GetDataset()
    Dim destinationTable = destination.Tables(0).AsEnumerable()

    ' Get Records which are not in destination table
    Dim ChangedRows = Nothing

    If IsNothing(PK) Then
        ChangedRows = destinationTable.AsEnumerable().Except(origTable.AsEnumerable(), DataRowComparer.Default)
    End If

    Dim List As New List(Of DataRow)

    For Each addRow In ChangedRows
        List.Add(addRow)
    Next

    Return List
End Function
问题是它最终只返回整个源行集

如何检查这些更改的行?我总是可以硬编码查询以返回我想要的内容,但这会带来问题,因为我需要对15个表进行比较,所以这将是一个完全混乱的局面

理想情况下,我需要一个解决方案,其中它将考虑源表中的可变数量列,以便与基本相同的目标表进行比较,并简单地比较数据行是否相等

对于每个源行,目标表中都应该有一个对应的行,因为新行的添加是在检查更新的行之前执行的

我也愿意使用LINQ以外的方法来实现这一点。


解决方案 最后,我实现了一个用于查询的自定义比较器,如下所示。它首先检查第一列的值是否匹配(在我的例子中是PK),如果匹配,则按列检查所有内容是否匹配

任何差异都会将我们返回的标志值设置为FALSE。如果没有任何问题,则返回TRUE。在本例中,我使用
=
来比较值之间的相等,而不是
Equals()
,因为我不关心严格的相等

结果数据行集用于使用
WHERE
子句中的第一列值(PK)更新数据库

Imports System.Data

Class MyDataRowComparer
  Inherits EqualityComparer(Of DataRow)

Public Overloads Overrides Function Equals(x As DataRow, y As DataRow) As Boolean
    If x.Item(0).ToString().Equals(y.Item(0).ToString()) Then
        ' If PK matches then check column-wise.
        Dim Flag As Boolean = True
        For Counter As Integer = 0 To x.ItemArray.Count - 1
            If Not x.Item(Counter) = y.Item(Counter) Then
                Flag = False
            End If
        Next
        Return Flag
    Else
        ' Otherwise don't bother and just skip.
        Return False
    End If
End Function

...
End Class

您需要一种方法来覆盖GetHashCode和Equals方法,或者提供一个EqualityComparer来成功,当前的方法进行对象引用比较,这将无法正常工作。对于IEnumerable更容易实现。Exception将在内部调用这些方法,因此在这种情况下需要重写DataRow类型谢谢,到目前为止这看起来不错。我可能会在
Equals
中的
DataRow
中迭代列,比较它们的值,并设置一个标志,这样它就不会与数据紧密耦合。会让你知道我的进展。是的,你需要定制这个零件,并确保检查各种条件,以便它能够完全符合预期的要求。对于Equals,所有列值都应该进行比较,对于Hashcode,您可以使用位运算符“^如果这有一些问题,那么我有另一种使用Contains的方法,它将精确地给出给定列表中不存在的元素,以便在我将逻辑放入
Equals()
后完美地完成这一技巧。我已将答案添加到我的原始问题中以供参考。
class MyDataRowComparer : IEqualityComparer<DataRow>
{      

    public bool Equals(DataRow x, DataRow y)
    {
        return x["ColumnName"].Equals(y["ColumnName"]);
        // Can add more columns to the Comparison
    }

    public int GetHashCode(DataRow obj)
    {
        return obj["ColumnName"].GetHashCode();
       // Can add more columns to calculate HashCode
    }    
}
ChangedRows = destinationTable.AsEnumerable()
             .Except(origTable.AsEnumerable(), MyDataRowComparer)