VB.Net 合并不遵守主键约束的数据表

VB.Net Merging datatables not obeying primary key constraints

我在使用 DataTable.Merge 方法和防止行重复时遇到困难。我有多个数据表需要合并为一个,包括需要合并的重复列。

我的数据表如下所示:

PID|140      PID|140          PID|144          PID|142
 1 | X         1|               1|               1|X
 2 |           2|X              2|X              2|X
 3 |           3|               3|X              3|X

当我合并它们时,它创建了重复的行值。

What I get:                      What I actually want:
PID|140|144|142                  PID|140|144|142
 1 | X |   |                      1 | X |   | X  
 2 |   |   |                      2 | X | X | X
 3 |   |   |                      3 |   | X | X
 1 |   |   |
 2 | X |   |
 3 |   |   | 
 1 |   |   |
 2 |   | X |
 3 |   | X | 
 1 |   |   | X
 2 |   |   | X
 3 |   |   | X 

我正在设置主键并在架构选项上使用 addWithKey,但合并时似乎忽略了主键约束。

  'writeTable being the destination of the merges'
  Dim primaryKey(1) As DataColumn
  primaryKey(1) = writeTable.Columns("PID")
  writeTable.PrimaryKey = primaryKey
  '...merging from a selected dataview to table'
      selected = view.ToTable("Selected", False,"PID","144")
      primaryKey(1) = selected.Columns("PID")
      selected.PrimaryKey = primaryKey
      writeTable.Merge(selected, False, MissingSchemaAction.AddWithKey)

Merge 旨在使用数据库中的更改来更新 DataTable。当您 Merge writeTable with selected 且第二个参数为 False 时,您会从 selected 中获得新值,1,Nothing 2,X 3,Nothing。 每个值都不同于初始值,因此初始值将被覆盖。当第二个参数为True时,得到1,X 2,Nothing 3,Nothing。初始值被保留。如果您希望 1 和 2 在 140 列中都显示 X,则必须过滤所选 table 以排除 140 列中的空值。然后只有 selected 中的非空值才会覆盖初始值。我是这样做的

    Dim NonNullselected = selected.Select($"[140] Is Not Null").CopyToDataTable

140左右的括号是必须的。必须处理以数字开头的字段。

我认为您的主要问题是分配主键。

Dim primaryKey(1) As DataColumn

这将创建一个包含 2 个元素的 DataColumn 数组,索引为 0 和 1。

primaryKey(1) = writeTable.Columns("PID")

这将向数组的第二个元素添加一列。第一个元素是 Nothing.

writeTable.PrimaryKey = primaryKey

我可以看出这是如何没有成功创建 PK。

我是这样做的

    dt.PrimaryKey = {dt.Columns(0)}

对于您的代码,

    writeTable.PrimaryKey = {writeTable.Columns("PID")}

大括号表示预期的数组,因此 属性 可以处理复合键。

Private writeTable As DataTable
Private selected As DataTable
Private Table3 As DataTable
Private Table4 As DataTable

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    CreateAndFillTables()
    Dim NonNullselected = selected.Select($"[140] Is Not Null").CopyToDataTable
    writeTable.Merge(NonNullselected, False, MissingSchemaAction.AddWithKey)
    writeTable.Merge(Table3, False, MissingSchemaAction.AddWithKey)
    writeTable.Merge(Table4, False, MissingSchemaAction.AddWithKey)
    DataGridView1.DataSource = writeTable
End Sub

Private Sub CreateAndFillTables()
    writeTable = CreateTable("140")
    writeTable.Rows.Add({1, 0})
    writeTable.Rows.Add({2})
    writeTable.Rows.Add({3})
    selected = CreateTable("140")
    selected.Rows.Add({1})
    selected.Rows.Add({2, 0})
    selected.Rows.Add({3})
    Table3 = CreateTable("144")
    Table3.Rows.Add(1)
    Table3.Rows.Add(2, 0)
    Table3.Rows.Add(3, 0)
    Table4 = CreateTable("142")
    Table4.Rows.Add(1, 0)
    Table4.Rows.Add(2, 0)
    Table4.Rows.Add(3, 0)
End Sub

Private Function CreateTable(SecondColumnName As String) As DataTable
    Dim dt As New DataTable
    dt.Columns.Add("PID", GetType(Integer))
    dt.Columns.Add(SecondColumnName, GetType(Integer))
    dt.PrimaryKey = {dt.Columns(0)}
    Return dt
End Function

结果