使用 LINQ 在 DataTable 中查找更新的行
Using LINQ to find updated rows in DataTable
我正在 VB.NET 中构建一个应用程序,我将数据从一个数据库推送到另一个数据库。源数据库是 SQL 服务器,目标是 MySQL.
我正在做的是首先为我用来进行比较的每个数据库中的每个 table 创建数据表。我以这样的方式编写查询,以便源和目标数据表包含完全相同的列和值,以便于比较。
应用程序的这一端工作正常。我接下来要做的是通过查找不存在的 PK 来查找目标数据库中不存在的行。然后我将这些新行毫无问题地插入到目标数据库中。
问题
我现在需要做的是在每个 table 中找到已更新的行,即与目标 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
问题在于它最终只是 return 整组源行。
如何检查这些更改的行?我总是可以对 return 我想要的查询进行硬编码,但这会带来问题,因为我需要对 15 table 进行比较,所以这将是一团糟。
理想情况下,我需要一个解决方案,它将考虑来自源 table 的可变数字列,以便与本质上相同的目标 table 进行比较,并简单地比较 DataRows 是否相等.
每个源行在目标 table 中应该有对应的行,因为添加新行是在检查更新的行之前执行的。
我也愿意使用 LINQ 以外的方法来实现这一点。
解决方案
最后,我实现了一个自定义比较器以在查询中使用,如下所示。它首先检查第一列值是否匹配(在我的例子中是 PK),如果匹配,那么我们逐列检查所有内容是否匹配。
任何差异都会将标志值设置为 FALSE,我们 return。如果没有任何问题,那么 TRUE 将被 returned。在这种情况下,我使用 =
来比较值之间的相等性而不是 Equals()
,因为我不关心严格相等性。
DataRows 的结果集用于 UPDATE
使用 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
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
}
}
现在 Except 语句如下:
ChangedRows = destinationTable.AsEnumerable()
.Except(origTable.AsEnumerable(), MyDataRowComparer)
我正在 VB.NET 中构建一个应用程序,我将数据从一个数据库推送到另一个数据库。源数据库是 SQL 服务器,目标是 MySQL.
我正在做的是首先为我用来进行比较的每个数据库中的每个 table 创建数据表。我以这样的方式编写查询,以便源和目标数据表包含完全相同的列和值,以便于比较。
应用程序的这一端工作正常。我接下来要做的是通过查找不存在的 PK 来查找目标数据库中不存在的行。然后我将这些新行毫无问题地插入到目标数据库中。
问题
我现在需要做的是在每个 table 中找到已更新的行,即与目标 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
问题在于它最终只是 return 整组源行。
如何检查这些更改的行?我总是可以对 return 我想要的查询进行硬编码,但这会带来问题,因为我需要对 15 table 进行比较,所以这将是一团糟。
理想情况下,我需要一个解决方案,它将考虑来自源 table 的可变数字列,以便与本质上相同的目标 table 进行比较,并简单地比较 DataRows 是否相等.
每个源行在目标 table 中应该有对应的行,因为添加新行是在检查更新的行之前执行的。
我也愿意使用 LINQ 以外的方法来实现这一点。
解决方案
最后,我实现了一个自定义比较器以在查询中使用,如下所示。它首先检查第一列值是否匹配(在我的例子中是 PK),如果匹配,那么我们逐列检查所有内容是否匹配。
任何差异都会将标志值设置为 FALSE,我们 return。如果没有任何问题,那么 TRUE 将被 returned。在这种情况下,我使用 =
来比较值之间的相等性而不是 Equals()
,因为我不关心严格相等性。
DataRows 的结果集用于 UPDATE
使用 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
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
}
}
现在 Except 语句如下:
ChangedRows = destinationTable.AsEnumerable()
.Except(origTable.AsEnumerable(), MyDataRowComparer)