gpt4 book ai didi

vb.net - 在 DataRowState.Modified 中合并两个相同的 DataTables 结果

转载 作者:行者123 更新时间:2023-12-03 09:59:26 25 4
gpt4 key购买 nike

假设如果两个相同的 DataTables 我错了吗?合并后每一行的状态会被保留吗?

看看这个简单的例子。它创建两个相同的表并合并 updated表带 original table 。但是返回的表在 original.GetChanges()不是 Nothing正如预期的那样。另外,original中每一行的状态表更改为 Modified .

那么我错过了什么?我真的必须创建自己的合并方法来实现这一目标吗?

Public Sub Test()

Dim original As DataTable = Me.CreateTableWithData()
Dim updated As DataTable = Me.CreateTableWithData()
Dim preserveChanges As Boolean = True
Dim msAction As MissingSchemaAction = MissingSchemaAction.Ignore

original.Merge(updated, preserveChanges, msAction)

Dim changes As DataTable = original.GetChanges()

MessageBox.Show(String.Format("Count={0}", If((changes Is Nothing), 0, changes.Rows.Count)), Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Information)

If (Not changes Is Nothing) Then changes.Dispose() : changes = Nothing
updated.Dispose() : updated = Nothing
original.Dispose() : original = Nothing

End Sub

Private Function CreateTableWithData() As DataTable
Dim table As New DataTable("TEST")
table.Columns.Add("ID", GetType(Integer))
table.Columns.Add("VALUE", GetType(String))
table.PrimaryKey = New DataColumn() {table.Columns(0)}
table.Rows.Add(1, "Value 1")
table.Rows.Add(2, "Value 2")
table.AcceptChanges()
Return table
End Function

输出: Count=2

编辑 - 解决方法

以下代码是这种奇怪(?)行为的解决方法。
Private Shared Sub Merge(target As DataTable, source As DataTable, preserveChanges As Boolean, msa As MissingSchemaAction)

target.Merge(source, preserveChanges, msa)

Dim row As DataRow
Dim column As DataColumn
Dim acceptChanges As Boolean

For Each row In target.Rows
If ((row.RowState = DataRowState.Modified) AndAlso ((row.HasVersion(DataRowVersion.Original)) AndAlso (row.HasVersion(DataRowVersion.Default)))) Then
acceptChanges = True
For Each column In target.Columns
If (Not Object.Equals(row.Item(column, DataRowVersion.Original), row.Item(column, DataRowVersion.Default))) Then
acceptChanges = False
Exit For
End If
Next
If (acceptChanges) Then
row.AcceptChanges()
End If
End If
Next

acceptChanges = Nothing
column = Nothing
row = Nothing

End Sub

最佳答案

在使用 DataTable 合并一段时间后,我找到了合并数据、保留更改并且不将所有现有行的 RowState 设置为 Modified 的最佳解决方案。

我发现如果您使用 DataTable Merge 并将 True 作为保留更改属性传递,则原始 DataTable 中的所有行都将其 RowState 设置为 Modified。如果您改为传递 false,则 RowStates 保持不变。

回到 DataTable.Merge(DataTable, Boolean, MissingSchemaAction) Method 的文档我找到了这个:

...In this scenario, the GetChanges method is first invoked. That method returns a second DataTable optimized for validating and merging. This second DataTable object contains only the DataTable and DataRow objects objects that were changed, resulting in a subset of the original DataTable...



从那里我开始意识到这个合并并不是真的打算直接与原始数据一起使用......相反,您应该对 GetChanges 方法返回的表进行合并(在保留更改时传递 true),然后合并更改表进入原始源,为保留更改参数传递 false。

为了证明这一点,我创建了以下类:
Class TableManger
Implements ComponentModel.INotifyPropertyChanged

Private _table1 As System.Data.DataTable
Private _table2 As System.Data.DataTable
Private _changesDetected As Integer = 0

Public ReadOnly Property Table1
Get
Return _table1
End Get
End Property
Public ReadOnly Property ChangesDetected As Integer
Get
Return _changesDetected
End Get
End Property

Public Sub New()
_table1 = CreateTableWithData()
_table1.AcceptChanges()

AddHandler _table1.RowChanged, New System.Data.DataRowChangeEventHandler(AddressOf Row_Changed)
End Sub

Public Sub MergeTables()

_table2 = _table1.Clone
Dim tableRows As New List(Of System.Data.DataRow)
For Each r In _table1.Rows
Dim dr2 = _table2.NewRow
For Each col As System.Data.DataColumn In _table1.Columns
dr2(col.ColumnName) = r(col.ColumnName)
Next
_table2.Rows.Add(dr2)
tableRows.Add(dr2)
Next
_table2.AcceptChanges()


If _table2.Rows.Count > 0 Then
_table2.Rows(0)(1) = "TB2 Changed"
End If

If _table1.Rows.Count > 0 Then
'_table1.Rows(0)(1) = "TB1 Change"'
_table1.Rows(1)(1) = "TB1 Change"
End If

_changesDetected = 0
Dim perserveChanges As Boolean = True
Dim msAction As System.Data.MissingSchemaAction = System.Data.MissingSchemaAction.Ignore

Dim changes As System.Data.DataTable = _table1.GetChanges()
If changes IsNot Nothing Then
changes.Merge(_table2, perserveChanges, msAction)
_table1.Merge(changes, False, msAction)
Else
_table1.Merge(_table2, False, msAction)
End If


MessageBox.Show(String.Format("Changes in Change Table: {0} {1}Changes Detected: {2}", If((changes Is Nothing), 0, changes.Rows.Count), System.Environment.NewLine, _changesDetected), "Testing")

RaiseEvent PropertyChanged(Me, New ComponentModel.PropertyChangedEventArgs("Table1"))
RaiseEvent PropertyChanged(Me, New ComponentModel.PropertyChangedEventArgs("ChangesDetected"))
End Sub

Private Sub Row_Changed(ByVal sender As Object, ByVal e As System.Data.DataRowChangeEventArgs)
Select Case e.Action
Case System.Data.DataRowAction.Change
If e.Row.RowState <> System.Data.DataRowState.Unchanged Then
_changesDetected += 1
End If
End Select
End Sub

Private Function CreateTableWithData() As System.Data.DataTable
Dim newTable As New System.Data.DataTable
Dim columnID As New System.Data.DataColumn("ID", GetType(Guid))
Dim columnA As New System.Data.DataColumn("ColumnA", GetType(String))
Dim columnB As New System.Data.DataColumn("ColumnB", GetType(String))
newTable.Columns.AddRange({columnID, columnA, columnB})
newTable.PrimaryKey = {newTable.Columns(0)}
For i = 0 To 5
Dim dr = newTable.NewRow
dr("ID") = Guid.NewGuid
dr("ColumnA") = String.Format("Column A Row {0}", i.ToString)
dr("ColumnB") = String.Format("Column B Row {0}", i.ToString)
newTable.Rows.Add(dr)
Next
Return newTable
End Function

Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
End Class

因此,在 MergeTables 方法中,我对 _table2 中的第一行进行了更改,并对 _table1 中的第二行进行了更改。

因为我更改了 _table1 中的第一行,所以 _table1.GetChanges 方法返回一个包含所有更改行的 DataTable(在本例中只是第一行)。

然后我将包含更改的表与 _table2 合并,并指示我要保留更改。

合并完成后,我知道结果将保留我在合并之前所做的更改,并且该表也将包含新数据(只要没有冲突)。将传入数据合并到更改表中的结果将解决数据中的任何冲突。

在我解决了这个表之后,我可以安全地合并到原始的 _table1 表中,表明保留更改 = false。因为将 false 作为保留更改参数传递不会导致原始数据的 RowState 更改,所以一切正常!我的更改被保留并且 RowStates 没有被修改!

快乐编码!

-弗林尼

关于vb.net - 在 DataRowState.Modified 中合并两个相同的 DataTables 结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21334757/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com