Столбец '' не допускает пустых значений. Но нет нулевого значения

Я делаю это на 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

* Ошибка целевого сайта *

Void 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 ответ

Я думаю, что вижу, в чем проблема, и меня не шокирует, что проблема в том, что вы используете 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 любой объект, который является экземпляром класса, является ссылочным типом и, следовательно, не будет скопирован при передаче по значению в любом случае.

Другие вопросы по тегам