列“”不允许为空。但是没有空值

时间:2018-11-16 04:15:05

标签: .net vb.net datatable datarow data-corruption

我正在VB.net上执行此操作

我有一个名为'dt'的数据表,其结构如下:

4列: 'OptionId' 'ChoiceId' '选择' “说明”

Datatable dt大约有800条记录。

我正在将其传递给函数:

Process(dt,"VehicleChoice;VehicleChoice", "Choice;Description", "Choice;Description", "ChoiceId;ChoiceId")

Public Sub Process(ByRef dt As DataTable, ByVal TableNames As String, ByVal ColumnNames As String, ByVal TableColumnNames As String, ByVal IdentityColumns As String)
    Dim aTableNames As String() = TableNames.Split(";")
    Dim aColumnNames As String() = ColumnNames.Split(";")
    Dim aTableColumnNames As String() = TableColumnNames.Split(";")
    Dim aIdentityColumns As String() = IdentityColumns.Split(";")

    ' remove readonly from columns
     For Each Column As String In aTableColumnNames
         dt.Columns(Column).ReadOnly = False
         dt.Columns(Column).MaxLength = -1
     Next

    ' ProcessFurther
     For Each row As DataRow In dt.Rows
         For i As Integer = 0 To aTableColumnNames.Length - 1
             ProcessFurther(row(aTableColumnNames(i)), aTableNames(i), aColumnNames(i), (row(aIdentityColumns(i)))
         Next
     Next
End Sub

Public Function ProcessFurther(ByRef OriginalValue As Object, ByVal TableName As String, ByVal ColumnName As String, ByVal IdentityValue As Integer) As String
     Dim OriginalValue = Some value which is not even related with any of these codes, but uses the params to retrieve this value.
     Return OriginalValue
End Function

所以这里的功能很简单,我不知道为什么会收到这个错误:(来自Log4Net)

*错误消息*

“ OptionId”列不允许为空。

*错误源*

System.Data

*错误目标站点*

无效CheckNullable(System.Data.DataRow)

*堆栈跟踪*

at System.Data.DataColumn.CheckNullable(DataRow row) 
at System.Data.DataColumn.CheckColumnConstraint(DataRow row, DataRowAction action) 
at System.Data.DataTable.RaiseRowChanging(DataRowChangeEventArgs args, DataRow eRow, DataRowAction eAction, Boolean fireEvent) 
at System.Data.DataTable.SetNewRecordWorker(DataRow row, Int32 proposedRecord, DataRowAction action, Boolean isInMerge, Boolean suppressEnsurePropertyChanged, Int32 position, Boolean fireEvent, Exception& deferredException) 
at System.Data.DataRow.EndEdit() 
at System.Data.DataRow.set_Item(DataColumn column, Object value) 
at ProcessFurther(DataTable& dt, String TableNames, String ColumnNames, String TableColumnNames, String IdentityColumns) in the For Loop (Stack trace has Line No of that For Loop, not the actual function.)

这里对我来说最大的困惑是,为什么/ OptionId在这里甚至是一个问题。在处理过程中甚至没有涉及,虽然它只是数据表的一部分。这对我完全没有任何意义。同样,这是随机发生的。可能会持续1-2分钟。它将消失约几个小时,并在一段时间后再次表现相同。它没有模式,出错或不出错时数据仍然相同。

如果有人对此有所帮助,请提供帮助,谢谢

1 个答案:

答案 0 :(得分:1)

我想我知道问题出在哪里了,问题是您在不应该使用ByRef的情况下感到惊讶。停止使用ByRef并了解其实际功能,然后仅在有特殊要求时使用它。您的ProcessFurther方法如下:

Public Function ProcessFurther(ByRef OriginalValue As Object,
                               ByVal TableName As String,
                               ByVal ColumnName As String,
                               ByVal IdentityValue As Integer) As String

这是您的称呼方式:

ProcessFurther(row(aTableColumnNames(i)),
               aTableNames(i),
               aColumnNames(i),
               row(aIdentityColumns(i)))

通过声明参数ByRef,您具体是说,应将方法内分配给该参数的所有内容分配回您最初传入的内容。首先传入的是row(aTableColumnNames(i)),因此,当您在方法第一行中分配给参数时,您将分配给DataRow的指定列。大概您要分配的是DBNull.Value,这就是为什么您会收到一条错误消息,告诉您该列不接受NULL。

当我对您关于从参数中删除ByRef的问题发表评论时,我实际上是在谈论dt方法的Process参数。那不是伤害你,但无论如何都不应该伤害你。在那个阶段,我还没有注意到您也在其他地方使用它。在这种情况下,它会伤害您。除非您特别需要,否则请勿使用ByRef。如果您不知道何时需要,请学习。这不是VB6,您可以在其中使用它来停止复制大对象。在VB.NET中,作为类实例的任何对象都是引用类型,因此,无论如何通过值传递时都不会被复制。