使用OleDB / Jet导入DataTable

时间:2016-05-30 16:45:22

标签: .net vb.net jet

我用Oledb编写了一个简短的函数,它应该读取大量的数据,但仍有几个问题我无法解决,它是关于在sql数据库中读取和插入分号分隔的数据

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. 我需要替换字符
  2.     value(i) = value(i).Replace("\t", Constants.vbTab).Replace("\n", Constants.vbLf).Replace("\r", Constants.vbCr).Replace("\""", """").Replace("\\", "\")
    

    但它通常仅适用于字符串

    1. 我需要识别整数,双精度,字符串等数据类型。我的第一个想法是通过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
      

      但仍不确定它是否可行

    2. 所有已读取的数据都应在1252 Codepage中编码。 这个没有真正起作用

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

      任何人都知道可以做些什么?

1 个答案:

答案 0 :(得分:2)

CSVHelper可以完成您想要的大部分内容。 FileHelpers也可能有用,我只是没有那么多。我不推荐VB的TextFieldParser因为它返回一个字符串数组而不是键入的数据。

OleDB提供了一种很好的导入方式,但保存到数据库提出了一个小小的挑战。所有加载的行都将RowState Unchanged。将其更改为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

我无法提供有关如何使用它的完整教程,但通常会创建一个类型(Class)来定义每列的数据类型(此处为RandItem),RandItemMap是另一个class,指定文件中这些属性的顺序。这样做,CSVHelper知道每列的数据类型并将为您转换。

有几种方法可以使用它,这种方式是从文件中一次读取一行并立即将该项目保存到数据库:csvData = csv.GetRecords(Of OleImportItem)()csvData初始化为IEnumberable(Of RandItem) ,因此在循环中一次仅加载一个项目,这使得它非常经济。

在循环中,代码从csv文件中获取一个类型item,然后将其映射到相应的参数并保存。这比批量复制数据和保存数据快20%左右;因为只加载了1个项目,因此内存密集程度更低。

对于较小的csv文件,您可以使用.ToArray()ToList()将文件加载到集合中。

注意导入/解析没有标题的文本文件与显示的有点不同,但同样简单。

听起来像CSVHelper可以消除洗衣清单中的大多数问题。