2

这里有许多类似的问题,但没有一个解释我的情况发生了什么;就这样吧。

我有以下(简化的)代码:

' row is a System.Data.DataRow
' _typeProperties is a Dictionary(Of String, PropertyInfo)

Dim data As New Dictionary(Of String, Object)
Dim elem As KeyValuePair(Of String, PropertyInfo)
Dim value As Object = Nothing
Try
    For Each elem In _typeProperties
        value = row.Item(elem.Key)
        data.Add(elem.Key, value)       ' NullReferenceException here
    Next
Catch ex As Exception When MyExceptionFilter(ex, data, elem, value)
End Try

有时我会在指示的行上收到 NullReferenceException。此异常极为罕见,我无法随意重现。但是,我可以修改我的应用程序,将其发送给客户,果然,几天后它会自行复制。

调用堆栈不是很有帮助:

StackTrace: 
  XXX.RowToType(DataRow row) in C:\XXX.vb:line 645.

此外,如您所见,我在 Catch 块中包含了一个异常过滤器。在那里我写了一个小型转储(异常的调用堆栈完好无损)。以下是 minidump 显示的调用堆栈的相关部分:

  ...
  App.exe!MyExceptionFilter( ex,  data,  elem,  value) Line 627
  App.exe!RowToType( row) Line 647 + 0x1f bytes
  [External Code]   
  App.exe!RowToType(System.Data.DataRow row) Line 645 + 0x112 bytes
  App.exe!SomeClass.get_Item(Integer index) Line 1141 + 0xe bytes   
  user32.dll!_InternalCallWinProc@20()  + 0x23 bytes    
  user32.dll!_UserCallWinProcCheckWow@32()  + 0x693 bytes   
  ...

异常发生在 [External Code] 块中的某处;然后执行 Catch 块的过滤器(第 2 行和第 1 行)。

在异常发生时,这些是三个涉及的变量的值:

  data: Not Nothing; 
  elem: Not Nothing; 
  elem.Value: Not Nothing (Int32 ID)
  elem.Key: Not Nothing
  value: Nothing

所以似乎绝对没有理由让 data.Add 抛出 NullReferenceException。

正如一些人在其他问题中所建议的那样,可能存在一些线程问题。但是,根据定义,我正在编写的字典只能对一个线程可见。(可以肯定的是,我还检查了 minidump 以确保没有线程正在执行相同的代码。)

我可能会默默地忽略这个异常,但我宁愿弄清楚这一点。

编辑。对于那些感兴趣的人,这里是整个代码:

Private Function RowToType(ByVal row As DataRow) As DataSourceRow
    Dim o = _typeActivator({})
    Dim data As New Dictionary(Of String, Object)
    Dim elem As KeyValuePair(Of String, PropertyInfo) = Nothing
    Dim value As Object = Nothing
    Try
        For Each elem In _typeProperties
            value = row.Item(elem.Key)
            If DBNull.Value.Equals(value) Then value = Nothing
            elem.Value.SetValue(o, value, Nothing)
            data.Add(elem.Key, value)           ' NullReferenceException here
        Next
    Catch ex As Exception When RowToTypeExceptionFilter(ex, row, data, elem, value)
    End Try

    o.Data = data
    Return o
End Function

仅供参考:_typeActivator创建 o动态类型的实例;不要认为它与问题有任何关系。

4

5 回答 5

0

对验证要添加的对象的内容很有用,它可能是 DBNull。

' row is a System.Data.DataRow'
' _typeProperties is a Dictionary(Of String, PropertyInfo)'
Dim data As New Dictionary(Of String, Object)

For Each pair As KeyValuePair(Of String, PropertyInfo) In _typeProperties

    'Validates that _typeProperties has no empty or nothing value as key'
    If String.IsNullOrEmpty(pair.Key) Then Continue For

    'Validates that the row contains the specified column'
    If Not row.Table.Columns.Contains(pair.Key) Then Continue For

    data.Add(pair.Key, If(IsDBNull(row(pair.Key)), "", row(pair.Key)))
    'data.Add(pair.Key, CheckNull(Of String)(row(pair.Key)))'
Next

    ''' <summary>
    ''' Evaluates the entry parameter to <c>DBNull</c>, and returns the default value of data type
    ''' </summary>
    ''' <typeparam name="T">Generic Type</typeparam>
    ''' <param name="Value">Object to evaluate</param>
    ''' <returns>If Value contains data, returns the value casted, otherwise returns the default value of type</returns>
    Public Shared Function CheckNull(Of T)(ByVal Value As Object) As T
        If Value Is Nothing OrElse System.Convert.IsDBNull(Value) Then
            If GetType(T) = GetType(String) Then
                Return DirectCast(DirectCast(String.Empty, Object), T)
            End If
        Else
            Return DirectCast(Value, T)
        End If
    End Function
于 2013-06-25T16:22:48.180 回答
0

正如其他人所建议的那样,调用堆栈中的行号(尽管在构建之间是一致的)总是引用错误的行。函数参数 ( row) 实际上是 NULL 值。谜团解开了。

于 2013-07-01T06:50:50.320 回答
0

value: Nothing将是获得空引用异常的正当理由。您的 DataRow 中的字符串可能是 Nothing(如果该列不存在,您会得到一个异常)。

于 2013-06-12T08:44:01.043 回答
0

我认为您的问题就在这里, row.Item(elem.Key), elem.key 不存在,这就是引发空异常的原因。您可以通过检查 row.Table.Columns.Contains(elem.key) 来检查列。

于 2013-06-25T21:32:38.830 回答
0

无所事事地看着doco。

当您将 Nothing 分配给对象变量时,它不再引用任何对象实例。如果变量之前引用了一个实例,将其设置为 Nothing 不会终止实例本身。只有在垃圾收集器 (GC) 检测到没有剩余的活动引用后,实例才会终止,并释放与其关联的内存和系统资源。

在将对象设置为“无”之前,系统可能认为对象具有有效引用。

这可能发生在字典值设置之外或字典本身内部。链接到键的对象可能会在设置后被释放。

于 2013-06-25T03:15:58.017 回答