Datarow维护DBNull,即使在删除它之后

时间:2017-06-21 07:28:52

标签: .net vb.net multithreading datatable

我是我的最后一招,无能为力,迷失了!

对于工作中的同步项目,我必须以通用方式将数据从数据库转换为Dynamics NAV记录。

工作中的数据库是旧的,包含空字段(“”)和NULL的混合,两者的含义相同。要以通用方式执行转换,我想从我检索的数据中删除所有DBNull,并将它们替换为默认值(由我选择)等效值。

由于数据非常庞大且转换操作非常繁重,我正在执行多线程转换,但稍后会更多。

在某个时刻,我会在检索完数据后执行此操作:

'...
Using DT As DataTable = ODB.DataTable(sql)

    CurrentRecordSet = DT.Rows.Cast(Of DataRow).ToList()
    CurrentRecordSet.ForEach(Sub(DR) RemoveDBNull(DR))

End Using
'...

至于RemoveDBNull,这有点像DataSetExtensions的Field(Of T)方法(事实上它使用它):

Public Sub RemoveDBNull(ByRef DR As DataRow)
    For Each Col As DataColumn In DR.Table.Columns
        Dim ColDataType As Type = Col.DataType
        Dim currentValue As Object
        Dim NewValue As Object
        Dim FieldMethod As Reflection.MethodInfo = GetType(DataRowExtensions).GetMethod("Field", {GetType(DataRow), GetType(String)})
        If ColDataType.IsValueType Then
            Dim NullableColDataType As Type = GetType(Nullable(Of)).MakeGenericType(ColDataType)
            currentValue = FieldMethod.MakeGenericMethod(NullableColDataType).Invoke(Nothing, {DR, Col.ColumnName})
            If IsNothing(currentValue) Then
                NewValue = Activator.CreateInstance(ColDataType)
            Else
                NewValue = currentValue
            End If
        Else
            currentValue = FieldMethod.MakeGenericMethod(ColDataType).Invoke(Nothing, {DR, Col.ColumnName})
            If IsNothing(currentValue) AndAlso ColDataType Is GetType(String) Then
                NewValue = String.Empty
            ElseIf currentValue IsNot Nothing Then
                NewValue = currentValue
            End If
        End If
        DR(Col) = NewValue
    Next
End Sub

最后,多线程翻译调用:

Private Sub PerformSyncTranslation(ByVal SyncType As String, ByVal TargetEntityType As String, ByRef dicEcDependencies As Dictionary(Of String, EntityCollection))
    Try
        Dim localdep = dicEcDependencies
        Parallel.ForEach(CurrentRecordSet, Sub(dr As DataRow)
                                               ecLocal.Add(dr.ToEntity(TargetEntityType, localdep, ecRetrieve.FirstOrDefault(Function(e) e(Cache.GetPrimaryKey(TargetEntityType)) = dr(SyncType))))
                                           End Sub)
        dicEcDependencies = localdep
    Catch ex As Exception
        Throw 'Don't mind this, debugging purposes only
    End Try
End Sub

现在我知道了一个事实,所有记录实际上都是由RemoveDBNull处理的,并且它做得非常好,并且尽管反射很快,但速度惊人。 然而仍然在ToEntity()内部,我看到我的一些数据行再次具有DBNull值。

我对于为什么会发生这种情况一无所知。我知道DataTables不是线程安全的,这就是我在对它们执行多线程操作之前删除空值并将数据行单独存储为单线程的原因。

希望我足够具体......

由于 安东

0 个答案:

没有答案