2016-05-30 39 views
1

我寫了OLEDB短函數,它應該讀大量的數據,但仍然有幾個問題我couldnt't解決,這是關於閱讀和插入分號在SQL數據庫導入到數據表使用OLEDB /噴氣

分離數據
Private Function GetCSVFile(ByVal file As String) As DataTable 

     Try 
      Dim dt As New DataTable 
      Dim ConStr As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & TextBox1.Text & ";Extended Properties=""TEXT;HDR=Yes;FMT=Delimited""" 
      Dim conn As New OleDb.OleDbConnection(ConStr) 

      Dim da As New OleDb.OleDbDataAdapter("Select * from " & _table & ".csv", conn) 
      da.Fill(dt) 
      Application.DoEvents() 
      getData = dt 
     Catch ex As OleDbException 
      MessageBox.Show(ex.Message) 
     Catch ex As Exception 
      MessageBox.Show(ex.Message) 
     End Try 
     Return getData 
    End Function 

1.它讀取整個文件,但我需要告訴函數,它應該只讀取50.000行並將它們傳遞給另一個步驟的步驟,它應該可能更好地工作for循環,因爲jet oledb不讀取文件大於1 GB

  1. 我需要替換字符
 
    value(i) = value(i).Replace("\t", Constants.vbTab).Replace("\n", Constants.vbLf).Replace("\r", Constants.vbCr).Replace("\""", """").Replace("\\", "\") 

但它通常僅適用於字符串

  • 我需要認識到的數據類型,如整數,雙,字符串等我的第一個想法是做在SQL查詢和檢查在表的TryParse

     
    
        Dim dtInserts As DataTable = db.GetDataTable("SELECT TOP 0 * FROM " & _table) 
          Dim ListOfTypes As New List(Of System.Type) 
        For Each _col As DataColumn In dtInserts.Columns 
           Dim _type As System.Type = _col.DataType 
           ListOfTypes.Add(_type) 
          Next 
          Dim _wert1 As String = "11.11.2011" 
          Dim _type1 As System.Type = ListOfTypes.Item(1) 
          If DateTime.TryParse(_wert1, New Date) Then 
          End If 
    

    ,但仍不能確定是否會工作

  • 所有已讀取的數據都應在1252代碼頁中進行編碼。 這一次並沒有真正的工作

  •  
        Dim ConStr As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & TextBox1.Text & ";Extended Properties=""TEXT;HDR=Yes;FMT=Delimited;CODEPAGE=1252""" 
    

    任何人知道什麼可以做?

    +1

    1個問題,請將4個捆綁在一起使其過於寬泛,太難以發佈簡短的答案。 – Plutonix

    +0

    看看這裏http://stackoverflow.com/questions/14044727/how-to-remove-character-from-a-given-datatable-column http://stackoverflow.com/questions/1499397/encoding-utf8-string- to-iso-8859-1-string-vb-net –

    +0

    #3和#4是非常可行的,#2如果沒有樣本數據就太模糊了,無法理解你想要做什麼,#1 *可能*能夠完成本地取決於數據,否則您可能需要添加一個步驟。如果您將問題細化到不太寬泛的地方,您可以在關閉之前得到一些答案 – Plutonix

    回答

    2

    CSVHelper可以做它聽起來像你想要的大部分。 FileHelpers也可能工作,我只是沒有與它合作。我不會推薦VB的TextFieldParser,因爲它返回一個字符串數組而不是鍵入的數據。

    OleDB提供了一種很好的導入方式,但是保存到數據庫中提出了一個小挑戰。所有加載的行將有一個RowStateUnchanged。要改變,要Added的唯一方法是將行復制到一個新表:

    For Each dr As DataRow In dtCSV.Rows 
        dtDest.Rows.Add(dr.ItemArray) 
    Next 
    

    它將工作,但作爲一個結果,你將有2個表和所有那些在一次加載行。事實證明,使用CSVHelper和一個簡單的INSERT查詢是最經濟的 - 因爲記錄是從IEnumerable<T>中獲取的,所以一次只能加載1個源記錄。它也比複製行快一點:500k行速度快了20%。

    注意:除了用分號分隔外,我們不知道數據是什麼樣子的......而且顯然有很多。

    Using sr As New StreamReader(CSVFilePath, False), 
        csv As New CsvReader(sr) 
    
        ' some CSVHelper config options 
        csv.Configuration.HasHeaderRecord = True 
        csv.Configuration.TrimFields = True 
        csv.Configuration.TrimHeaders = True 
        csv.Configuration.Delimiter = ";" 
        csv.Configuration.IsHeaderCaseSensitive = False 
        csv.Configuration.RegisterClassMap(Of RandItem.RandItemMap)() 
    
        ' get the file into IEnumerable collection 
        Dim csvData = csv.GetRecords(Of OleImportItem)() 
    
        Dim SQL = <sql> 
           INSERT INTO RandomData 
            (Foo, Bar, Cat, Dog...) 
           VALUES 
            (@p1, @p2, @p3, @p4...) 
          </sql>.Value 
    
        Using dbcon As New OleDbConnection(ACEConnStr) 
         Using cmd As New OleDbCommand(SQL, dbcon) 
          dbcon.Open() 
    
          ' create the parameters 
          cmd.Parameters.Add("@p1", OleDbType.VarChar) 
          cmd.Parameters.Add("@p2", OleDbType.VarChar) 
          cmd.Parameters.Add("@p3", OleDbType.Integer) 
          cmd.Parameters.Add("@p4", OleDbType.Integer) 
          ... 
          ' load one item at a time, to save it 
          For Each item In csvData 
           cmd.Parameters("@p1").Value = item.Foo 
           cmd.Parameters("@p2").Value = item.Bar 
           cmd.Parameters("@p3").Value = item.Cat 
           cmd.Parameters("@p4").Value = item.Dog 
           ... 
           cmd.ExecuteNonQuery() 
          Next 
         End Using 
        End Using 
    End Using 
    

    我不能就如何使用它完整的教程,但一般而言,您創建一個類型(類),它定義了數據類型爲每列(在這裏,RandItem),該RandItemMap是另一個類指定文件中這些屬性的順序。這樣做,CSVHelper知道每列的數據類型,並將爲您轉換。

    有幾種方法來使用它,這種方式是讀一行在從文件時間,並立即保存該項目到數據庫:csvData = csv.GetRecords(Of OleImportItem)()初始化csvData作爲IEnumberable(Of RandItem),所以只有一個項目在加載在循環中的時間,這使得它非常經濟。

    在循環中,代碼從csv文件中獲得一個類型item,然後將其映射到相應的參數並保存。這比將數據批量複製並保存到DataTable快20%左右;並且由於只有1個項目被加載,因此內存密集程度要低得多。


    對於較小的CSV文件,你可以使用.ToArray()ToList()將文件加載到集合。

    注意導入/解析沒有標題的文本文件與示例有點不同,但同樣簡單。

    聽起來像CSVHelper可能會避免洗衣清單中的大多數問題。

    +0

    csv助手是一種很好的方法,但我有非常糟糕的閱讀器閱讀經驗,因爲閱讀大文件需要從字面上看來,有沒有什麼方法可以讀取1252中編碼的文件並用字符替換? – Sparkm4n

    +0

    我非常懷疑streamreader會是瓶頸。使用上面的代碼,它將100k行讀入一個打印對象。我沒有做任何事情,因爲該對象是時間StreamReader。但是,它確實意味着創建了一個對象,並將不重要的行數據解析並複製到該對象中。經過的時間:903毫秒。但1GB文件需要時間。第2項中的東西也需要時間 - 字符串是不可變的,因此一行創建5個數據,將數據複製到每個數據。 1252沒有什麼特別之處 - 它是Windows默認編碼。 – Plutonix

    +0

    另一個測試,這次將所有10萬條記錄以10k的批次發佈到MySql數據庫:少於2分鐘。更多的行需要更多的時間,而你對他們做的事情需要更多的時間。 – Plutonix