【问题标题】:Updating a tableadapter with duplicated keys使用重复键更新 tableadapter
【发布时间】:2013-09-04 20:33:03
【问题描述】:

我是更新数据库的新手,显然我不擅长。

详情:

  • 我使用 tableadapter(我不知道这是否是最好的方法)在 .mdf 文件中引用我的数据库
  • 我的表有两列,第一列是Primary Key
  • 表格已经有一些行了
  • 我在我的表格适配器中填写:Me.CCListTableAdapter.Fill(Me.HQSdbDataSet.CCList)

我想做什么:

  1. 我根据我的 CCListTable 创建了一个新数据表:Dim ccDataTable As CCListDataTable = New CCListDataTable
  2. 我使用 CsvReader 将具有新行(> 3000 行)的 .csv 文件导入到这个新数据表中。我的数据库中已经存在一些行
  3. 然后我尝试将这些新行添加到 tableadapter 中:

    Me.CCListBindingSource.EndEdit() Me.CCListTableAdapter.Update(ccDataTable)

但它不起作用,我得到一个 SqlExceptionViolation of PRIMARY KEY [...] Cannot insert duplicate key。好的,就像我说的那样,我知道有重复的键,但我不想插入这些,而只想用新行更新 tableadapter。

这里是我创建的用于导入我的 CSV 的子目录(如果有帮助的话):

Public Sub ImportCSV2Data(ByVal filename As String, ByRef datatable As DataTable, ByVal column2Import() As Integer,
                          ByVal tableAlreadyExist As Boolean)

    Dim csvCopy As CachedCsvReader = New CachedCsvReader(New StreamReader(filename), True, ";"c)
    csvCopy.MissingFieldAction = MissingFieldAction.ReplaceByEmpty

    Dim headers() As String = csvCopy.GetFieldHeaders
    If column2Import.Length > 0 AndAlso column2Import(0) > -1 Then
        If tableAlreadyExist Then
            While csvCopy.ReadNextRecord()
                Dim csvRow As DataRow = datatable.NewRow
                Dim i As Integer = 0
                For Each column As Integer In column2Import
                    Select Case datatable.Columns(i).DataType.Name
                        Case "String"
                            If String.IsNullOrEmpty(csvCopy(column)) Then
                                csvRow(i) = ""
                            Else
                                csvRow(i) = Convert.ToString(csvCopy(column))
                            End If
                        Case "Int32"
                            If String.IsNullOrEmpty(csvCopy(column)) Then
                                csvRow(i) = DBNull.Value
                            Else
                                csvRow(i) = Convert.ToInt32(csvCopy(column))
                            End If
                        Case "Double"
                            If String.IsNullOrEmpty(csvCopy(column)) Then
                                csvRow(i) = DBNull.Value
                            Else
                                csvRow(i) = Convert.ToDouble(csvCopy(column))
                            End If
                        Case "DateTime"
                            If String.IsNullOrEmpty(csvCopy(column)) Then
                                csvRow(i) = Nothing
                            Else
                                csvRow(i) = Convert.ToDateTime(csvCopy(column))
                            End If
                        Case "Boolean"
                            If String.IsNullOrEmpty(csvCopy(column)) Then
                                csvRow(i) = DBNull.Value
                            Else
                                csvRow(i) = Convert.ToBoolean(csvCopy(column))
                            End If
                    End Select
                    i += 1
                Next
                datatable.Rows.Add(csvRow)
            End While
        Else
            For Each column As Integer In column2Import
                datatable.Columns.Add(headers(column))
            Next
            While csvCopy.ReadNextRecord()
                Dim csvRow As DataRow = datatable.NewRow
                Dim i As Integer = 0
                For Each column As Integer In column2Import
                    csvRow(i) = csvCopy(column)
                    i += 1
                Next
                datatable.Rows.Add(csvRow)
            End While
        End If
    Else
        If tableAlreadyExist Then
            While csvCopy.ReadNextRecord()
                Dim csvRow As DataRow = datatable.NewRow
                For i = 0 To csvCopy.FieldCount - 1
                    Select Case datatable.Columns(i).DataType.Name
                        Case "String"
                            If String.IsNullOrEmpty(csvCopy(i)) Then
                                csvRow(i) = ""
                            Else
                                csvRow(i) = Convert.ToString(csvCopy(i))
                            End If
                        Case "Int32"
                            If String.IsNullOrEmpty(csvCopy(i)) Then
                                csvRow(i) = DBNull.Value
                            Else
                                csvRow(i) = Convert.ToInt32(csvCopy(i))
                            End If
                        Case "Double"
                            If String.IsNullOrEmpty(csvCopy(i)) Then
                                csvRow(i) = DBNull.Value
                            Else
                                csvRow(i) = Convert.ToDouble(csvCopy(i))
                            End If
                        Case "DateTime"
                            If String.IsNullOrEmpty(csvCopy(i)) Then
                                csvRow(i) = Nothing
                            Else
                                csvRow(i) = Convert.ToDateTime(csvCopy(i))
                            End If
                        Case "Boolean"
                            If String.IsNullOrEmpty(csvCopy(i)) Then
                                csvRow(i) = DBNull.Value
                            Else
                                csvRow(i) = Convert.ToBoolean(csvCopy(i))
                            End If
                    End Select
                Next
                datatable.Rows.Add(csvRow)
            End While
        Else
            For Each header As String In headers
                datatable.Columns.Add(header)
            Next
            While csvCopy.ReadNextRecord()
                Dim csvRow As DataRow = datatable.NewRow
                For i = 0 To csvCopy.FieldCount - 1
                    csvRow(i) = csvCopy(i)
                Next
                datatable.Rows.Add(csvRow)
            End While
        End If
    End If
End Sub

我错过了什么?

【问题讨论】:

  • 我的主键是Int,“导入行时需要知道如何设置键的值”是什么意思?
  • 我们需要知道列是否有自增属性。您有主键违规,因此我们需要查看从 csv 导入行的代码的部分代码。问题似乎很明显,但用这样的信息是不可能解决的。
  • 否,该列没有自动增量属性。我将编辑我的问题以发布导入 CSV 的代码。但我不认为问题来自导入,因为通过Console.Writeline 我可以看到它很好地导入了所有内容。我认为问题出在重复键:一个存在于我的数据表中,其中包含我导入的行,另一个存在于我的旧数据库中。
  • 我会尽力提供帮助,但我想知道之前,导入 CSV 的代码是否有效?尝试更新表时出现异常,但此时是否正确?例如,您是否尝试在更新代码之前的某处显示数据。 - 从 csv 导入的代码似乎是通用的(不是特定于您的 DataTable)。 CSV 文件中的数据必须具有相同的架构(即相同的列数,相同的Order,相同的DataType)。
  • 好的,所以主键的原则是它必须是唯一的。由于表中已有数据,因此您需要确保 CSV 文件中的数据不包含重复项。 否则,您需要编写自己的逻辑来将重复的键替换为其他键(您提到键没有增量属性)。有意义吗?

标签: sql vb.net datatable sql-update tableadapter


【解决方案1】:

这是解决我问题的代码:

    'Create a DataTable with the same schema of your DataBase
    Dim ccDataTable As CCListDataTable = New CCListDataTable

    'Import here your csvFile into your new DataTable
    Call ImportCSV2Data(dialog2openFile.FileName, ccDataTable, {0, 2}, True)

    'Merge it with the correct DataTable from your Database (False to recognize the changes)
    Me.HQSdbDataSet.CCList.Merge(ccDataTable, False)

    'Then update your DataBase
    Me.CCListBindingSource.EndEdit()
    Me.CCListTableAdapter.Update(Me.HQSdbDataSet.CCList)

如果您在调试模式下关闭应用程序时丢失了更改,这是正常的,因为您有两个数据库,一个在您的应用程序中,另一个在调试文件夹中,当您进入调试模式但当您在没有调试模式的情况下启动您的应用程序就可以了。 其他解决方案:在你的数据库中选择'NEVER COPY'

【讨论】:

    猜你喜欢
    • 2018-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-11
    • 2015-05-20
    • 1970-01-01
    相关资源
    最近更新 更多