使用 OleDB/Jet 导入 DataTable
Posted
技术标签:
【中文标题】使用 OleDB/Jet 导入 DataTable【英文标题】:Import to DataTable using OleDB/Jet 【发布时间】:2016-05-30 16:45:22 【问题描述】:我用 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 行并将它们传递给另一个函数 step for step,它应该在 for 循环中更好地工作,因为 jet oledb 不会读取大于 1 GB 的文件
-
我需要替换字符
但它通常只适用于字符串
我需要识别整数、双精度、字符串等数据类型。我的第一个想法是通过 sql 查询并通过 tryparse 检查表
Dim dtInserts As DataTable = db.GetDataTable("SELECT TOP 0 * FROM " & _table) 将 ListOfTypes 暗淡为新列表(System.Type) 对于 dtInserts.Columns 中的每个 _col 作为 DataColumn 暗淡 _type 作为 System.Type = _col.DataType ListOfTypes.Add(_type) 下一个 暗淡 _wert1 As String = "11.11.2011" Dim _type1 As System.Type = ListOfTypes.Item(1) If DateTime.TryParse(_wert1, New Date) Then 万一但仍然不确定它是否会起作用
所有已读取的数据都应编码在 1252 代码页中。 这个真的不行
有人知道可以做什么吗?
【问题讨论】:
请一次提出 1 个问题,将 4 个问题捆绑在一起会使发布简短答案的范围太广且太难。 看这里***.com/questions/14044727/…***.com/questions/1499397/… #3 和#4 非常可行,#2 太模糊,没有样本数据,无法理解您要做什么,#1 可能可以原生完成取决于数据,否则您可能需要添加一个步骤。如果您将问题细化为不那么广泛的问题,您可能会在结束之前得到一些答案 你应该删除Application.DoEvents()
这一行——它会导致奇怪的事情发生。
如果需要解析CSV文件,可以使用CSV解析器。 TextFieldParser class 可能就足够了。那么您的程序将不受 JET 的限制。
【参考方案1】:
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
我不能给出一个完整的使用教程,但通常你创建一个类型(类),它定义了每一列的数据类型(这里,RandItem
),RandItemMap
是另一个类,它指定文件中这些属性的顺序。这样做时,CSVHelper 知道每一列的数据类型,并会为您转换。
有几种使用方法,这种方法是从文件中一次读取一行并立即将该项目保存到数据库中:csvData = csv.GetRecords(Of OleImportItem)()
将csvData
初始化为IEnumberable(Of RandItem)
,所以只有 在循环中一次加载一个项目,这使得它非常经济。
在循环中,代码从 csv 文件中获取输入的 item
,然后将其映射到相应的参数并保存。这比将数据批量复制到DataTable并保存快20%左右;由于只加载了 1 个项目,因此占用的内存要少得多。
对于较小的 csv 文件,您可以使用 .ToArray()
或 ToList()
将文件加载到集合中。
注意导入/解析不带标题的文本文件与显示的略有不同,但同样简单。
听起来 CSVHelper 可能会消除您洗衣清单中的大多数问题。
【讨论】:
csv helper 是一个好方法,但我对流式阅读器的体验非常糟糕,因为读取大文件需要几个小时,有没有办法读取以 1252 编码并替换为字符的文件? 我非常怀疑流式阅读器会成为瓶颈。使用上面的代码,它将 100k 行读入一个类型化的对象。我没有对它做任何事情,因为对象是为 StreamReader 计时的。但是,这确实意味着创建了一个对象,并将非平凡的行数据解析并复制到其中。经过的时间:903 毫秒。但是一个 1GB 的文件需要时间。项目符号 2 中的内容也需要时间 - 字符串是不可变的,因此一行创建 5 个连续复制数据位到每个。 1252 没有什么特别之处——它是 windows 默认编码。 另一个测试,这次将所有 100k 记录以 10k 的批次发布到 mysql DB:不到 2 分钟。更多行将花费更多时间,而您对它们执行的操作将花费更多时间。 @Sparkm4n 你知道文件中有多少行吗?我正在用 Dapper 测试一些东西,我想到了这个 Q(因为我正在用相同的数据进行测试)。 我有几个大文件,最大的一个大约有。一百万行以上是关于使用 OleDB/Jet 导入 DataTable的主要内容,如果未能解决你的问题,请参考以下文章
我应该通过 OleDb Jet4.0 读取一个 excel 文件并保存到数据集中吗?
使用 Asp.net 将 Excel 导入 DataTable
Excel操作--使用NPOI导入导出Excel为DataTable