2014-07-25 45 views
0

我有下面的代码,我在我的项目中为datatable创建了扩展。它实际上工作。只是想知道是否有任何优化可以通过。谢谢。 =)在数据表中为NULL设置默认值

我知道这个问题应该以某种方式属于CR。只是通过问。

<Extension()> 
Public Function HasNull(ByVal dataTable As DataTable) As Boolean 
    For Each column As DataColumn In dataTable.Columns 
     If dataTable.Rows.OfType(Of DataRow)().Any(Function(r) r.IsNull(column)) Then 
      Return True 
     End If 
    Next 
    Return False 
End Function 

<Extension()> 
Public Function SetDefaultForNull(ByVal dataTable As DataTable) As DataTable 
    For Each row As DataRow In dataTable.Rows 
     For Each col As DataColumn In dataTable.Columns 
      Dim value As Object = row(col) 
      If IsDBNull(value) Then 
       Dim dataType As String = col.DataType.ToString 

       Select Case dataType 
        Case "System.DateTime" 
         value = New DateTime 
        Case "System.Decimal", "System.Int16", "System.Int32", "System.Int64" 
         value = 0 
        Case "System.String" 
         value = String.Empty 
        Case "System.Boolean" 
         value = False 
        Case Else 
         value = 0 
       End Select 
       row(col) = value 
      End If 
     Next 
    Next 
    Return dataTable 
End Function 
+0

我会处理的情况是输入表是'Nothing',要么抛出'ArgumentNullException'或返回'True' /'False'。另一个小改进:我会循环行而不是列。考虑到除最后一列外,所有列都是非空的。在检测到空值之前,您将循环所有列的所有行。如果你循环行,你确定已经在第一行(如果最后一列为空)。 –

+0

@Tim Schmelter。感谢您的回应。我的第二个功能的意图是为每个空单元设置一个默认值。所以我会无论如何不得不遍历每一行和每列? – HengChin

+0

我主要是指第一种方法。 –

回答

2

,所以我会在这里把我的意见,对于它的价值:

根据第一种方法: 我会处理的输入表是Nothing的情况下,无论是抛出一个ArgumentNullException或回报True/False

另一个小改进:我会循环行而不是列。考虑到除最后一列外,所有列都是非空的。在检测到空值之前,您将循环所有列的所有行。如果你循环行,你已经确定已经在第一行(如果最后一列充满了空值)。

因此,像这样:

<Extension()> 
Public Function HasNull(dataTable As DataTable) As Boolean 
    If dataTable Is Nothing Then 
     Throw New ArgumentNullException("dataTable must be initialized", "dataTable") 
    End If 
    Dim allColumns = dataTable.Columns.Cast(Of DataColumn).ToList() ' materialize 
    Dim hasNullField As Boolean = dataTable.AsEnumerable(). 
     Any(Function(row) allColumns.Any(Function(c) row.IsNull(c))) 
    Return hasNullField 
End Function 

第二种方法可以使用这个扩展,而不是让所有类型的默认值:

<Extension()> 
Public Function GetDefaultValue(t As Type) As Object 
    If t.IsValueType Then 
     Return Activator.CreateInstance(t) 
    Else 
     Return Nothing 
    End If 
End Function 

第二种方法本身可能再在这个实施方法(使之成为Sub):

<Extension()> 
Public Sub SetDefaultForNull(dataTable As DataTable) 
    For Each row As DataRow In dataTable.Rows 
     For Each col As DataColumn In dataTable.Columns 
      If row.IsNull(col) Then 
       row.SetField(col, col.DataType.GetDefaultValue()) 
      End If 
     Next 
    Next 
End Sub 

与测试这个样本数据:

Dim table As New DataTable 
table.Columns.Add("ID", GetType(Int32)) 
table.Columns.Add("Name", GetType(String)) 
table.Columns.Add("Date", GetType(DateTime)) 
table.Rows.Add(1, "test", DateTime.Now) 
table.Rows.Add(DBNull.Value, Nothing, Nothing) 
table.Rows.Add(Nothing, DBNull.Value, DBNull.Value) 
If table.HasNull() Then 
    table.SetDefaultForNull() 
End If 

结果:

1  test 25.07.2014 15:05:29 
0    01.01.0001 00:00:00 
0    01.01.0001 00:00:00 

编辑:如果你真的想取代null串空字符串,你可以添加参数GetDefaultValue

<Extension()> 
Public Function GetDefaultValue(t As Type, replaceNullStringsWithEmpty As Boolean) As Object 
    If t.IsValueType Then 
     Return Activator.CreateInstance(t) 
    ElseIf replaceNullStringsWithEmpty AndAlso t = GetType(String) Then 
     Return "" 
    Else 
     Return Nothing 
    End If 
End Function 

不过,我不喜欢单一类型的例外,也不可能区分之后,再使用和""。我会做最后一步你想要显示字符串的东西。

+0

,谢谢。我对GetDefaultValue方法进行了一些修改,因为我发现它不适用于字符串数据类型,因为它被归类为非值类型。你有更好的主意吗? – HengChin

+0

@chinz:你真的想用空字符串替换空字符串吗?为什么?以后你将无法区分它们。我想在最后一步替换它们,当你想在某处显示它们时。否则,你仍然需要一个'Select Case'来检查它是否是字符串。 –

+0

我不知道我是否做得对。我的表单中有很多文本框和标签控件。每次我从数据表中取值时,我都会用IsDBNull检查DBNULL。不知何故,通常,我可能只留下了一两个(当一个新的列如果添加到数据库可能吗?)?所以我会用空字符串替换所有的空值,然后永远不会被忘记。 – HengChin