2014-07-25 42 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