我是我的最后一招,无能为力,迷失了!
对于工作中的同步项目,我必须以通用方式将数据从数据库转换为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不是线程安全的,这就是我在对它们执行多线程操作之前删除空值并将数据行单独存储为单线程的原因。
希望我足够具体......
由于 安东