使用 OleDB/Jet 导入到 DataTable
Import to DataTable using OleDB/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 的文件
- 我需要替换字符
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 Codepage编码。
这个真的不行
Dim ConStr As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & TextBox1.Text & ";Extended Properties=""TEXT;HDR=Yes;FMT=Delimited;CODEPAGE=1252"""
有人知道可以做什么吗?
CSVHelper can do most of what it sounds like you want. FileHelpers 也可能有用,我只是没怎么用过它。我不会推荐 VB 的 TextFieldParser
因为它 returns 是一个字符串数组而不是类型化数据。
OleDB
提供了一种很好的导入方式,但保存到数据库是一个小挑战。所有加载的行的 RowState
为 Unchanged
。将其更改为 Added
的唯一方法是将行复制到新的 table:
For Each dr As DataRow In dtCSV.Rows
dtDest.Rows.Add(dr.ItemArray)
Next
它会起作用,但结果是,您将同时加载 2 table 和所有这些行。事实证明,使用 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
,然后将其映射到相应的参数并保存。这比将数据批量复制到DataTable并保存快20%左右;而且内存占用更少,因为只加载了 1 个项目。
对于较小的 csv 文件,您可以使用 .ToArray()
或 ToList()
将文件加载到 collection。
注意 Importing/parsing 没有 headers 的文本文件与显示的略有不同,但同样简单。
听起来 CSVHelper 可能会解决您洗衣清单中的大多数问题。
我用 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 的文件
- 我需要替换字符
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 Codepage编码。 这个真的不行
Dim ConStr As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & TextBox1.Text & ";Extended Properties=""TEXT;HDR=Yes;FMT=Delimited;CODEPAGE=1252"""
有人知道可以做什么吗?
CSVHelper can do most of what it sounds like you want. FileHelpers 也可能有用,我只是没怎么用过它。我不会推荐 VB 的 TextFieldParser
因为它 returns 是一个字符串数组而不是类型化数据。
OleDB
提供了一种很好的导入方式,但保存到数据库是一个小挑战。所有加载的行的 RowState
为 Unchanged
。将其更改为 Added
的唯一方法是将行复制到新的 table:
For Each dr As DataRow In dtCSV.Rows
dtDest.Rows.Add(dr.ItemArray)
Next
它会起作用,但结果是,您将同时加载 2 table 和所有这些行。事实证明,使用 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
,然后将其映射到相应的参数并保存。这比将数据批量复制到DataTable并保存快20%左右;而且内存占用更少,因为只加载了 1 个项目。
对于较小的 csv 文件,您可以使用 .ToArray()
或 ToList()
将文件加载到 collection。
注意 Importing/parsing 没有 headers 的文本文件与显示的略有不同,但同样简单。
听起来 CSVHelper 可能会解决您洗衣清单中的大多数问题。