.net 将XML文档拆分为多个部分
我知道这个问题已经被问过很多次了,但当我搜索时,我找到了12年前的答案,我正在寻找一个更现代的解决方案。我有一个XML文件,看起来像.net 将XML文档拆分为多个部分,.net,sql-server,xml,vb.net,.net,Sql Server,Xml,Vb.net,我知道这个问题已经被问过很多次了,但当我搜索时,我找到了12年前的答案,我正在寻找一个更现代的解决方案。我有一个XML文件,看起来像 9238972 R01 加利福尼亚州 9238973 R012 加利福尼亚州 9238974 R013 加利福尼亚州 我需要将每个元素作为XML元素保存到MSSQL 2016服务器 我当前的代码速度太慢,无法完成100多万个元素。我有文本文件,每个文件大约有100000条记录。我目前的代码是: Dim rdr作为新的StreamReader(ofdXML.Fi
9238972
R01
加利福尼亚州
9238973
R012
加利福尼亚州
9238974
R013
加利福尼亚州
我需要将每个
元素作为XML元素保存到MSSQL 2016服务器
我当前的代码速度太慢,无法完成100多万个
元素。我有文本文件,每个文件大约有100000条记录。我目前的代码是:
Dim rdr作为新的StreamReader(ofdXML.FileName)
而(rdr.Peek>=0)
varLine=rdr.ReadLine
sTag=varLine.Contains(“”)
eTag=varLine.Contains(“”)
如果是sTag和eTag那么
appLine=varLine
如果appLine.Contains(“”),则
appID=appLine.Substring(Len(“”),appLine.IndexOf(“/APPLICATION\u ID”)-Len(“”-1)
如果结束
艾尔塞夫·斯塔格
v1=真
appLine=varLine
如果appLine.Contains(“”),则
appID=appLine.Substring(Len(“”),appLine.IndexOf(“/APPLICATION\u ID”)-Len(“”-1)
如果结束
那么艾尔塞夫·埃塔格呢
appLine=appLine和varLine
v1=错误
埃尔塞夫
appLine=appLine和varLine
如果appLine.Contains(“”),则
模糊Xi为整数=Apple。IndexOf(“席ID>”)+ 4
appID=appLine.Substring(xi,appLine.IndexOf(“/APPLICATION\u ID”)-(xi+1))
如果结束
如果结束
我已经尝试过LINQ,但是我无法获得VB.NET的正确语法,这可能会更快。我想要的是一种更有效的拆分和保存方法。目前,用100000行元素来处理一个文件需要16个小时。 如果这是一次性导入,您可以考虑编写转换器来读取XML文件并吐出一个管道分隔文件。然后,您可以使用SQL Server的大容量插入命令或导入数据向导非常轻松地导入它 执行转换的代码看起来像
Using sw As New System.IO.StreamWriter("outputfile.txt")
Dim xdoc As New System.Xml.XmlDocument
xdoc.Load("InpurtFilename")
For Each row As System.Xml.XmlNode In xdoc.SelectNodes("//xsi:row")
Dim ApplicationId As String = row.SelectSingleNode("xsi:APPLICATION_ID").InnerText
Dim Activity As String = row.SelectSingleNode("xsi:ACTIVITY").InnerText
Dim AdministeringIC As String = row.SelectSingleNode("xsi:ADMINISTERING_IC").InnerText
sw.WriteLine(String.Format("{0}|{1}|{2}", ApplicationId, Activity, AdministeringIC))
Next
End Using
使用XML序列化
创建类来表示您的文件
Imports System.IO
导入System.Xml.Xml
公共类项目
公共属性行作为列表(行的列表)
末级
公共类行
公共属性应用程序\u ID为整数
作为字符串的公共属性活动
作为字符串管理的公共属性
末级
(我编写了一些代码来创建一个约140 MB的100万XML文件。)
Private Async Sub Button1\u单击(发送方作为对象,e作为事件参数)处理按钮1。单击
将sw调暗为新秒表()
sw.Start()
wait Task.Factory.StartNew(writeProjects的地址)
sw.Stop()
Console.WriteLine($“在{sw.elapsedmillesons}ms.中创建的文件”)
端接头
私有子写项目()
Dim p作为新项目()
p、 行=新列表(行中)()
对于i=1到1000000
将r调暗为具有{
.Application_ID=i,
.Activity=$“R0{i}”,
.管理_IC=“CA”
}
p、 行。添加(r)
下一个
将writer用作新的StreamWriter(“filename.xml”)
Dim s作为新的XmlSerializer(GetType(项目))
s、 序列化(编写器,p)
终端使用
端接头
在2346毫秒内创建文件
并使用此代码读取文件并写入数据库
Private Async Sub Button2\u单击(发送方作为对象,e作为事件参数)处理按钮2。单击
将sw调暗为新秒表()
sw.Start()
Dim p=wait Task.Factory.StartNew(readProjects的地址)
sw.Stop()
Console.WriteLine($“以{sw.elapsedmillesons}ms.格式读取文件”)
sw.Restart()
wait Task.Factory.StartNew(writeSQL、p、TaskCreationOptions.None的地址)
sw.Stop()
WriteLine($“在{sw.elapsedmillesons}ms.中写入SQL”)
端接头
私有函数readProjects()作为项目
Dim p As项目
将reader用作新的StreamReader(“filename.xml”)
Dim s作为新的XmlSerializer(GetType(项目))
p=DirectCast(反序列化(读取器),项目)
终端使用
返回p
端函数
私有子写SQL(o作为对象)
Dim p=直接广播(o,项目)
对于p.行中的每个r
'插入每一行
暗q=
$“插入[表](应用程序ID、活动、管理IC)
值({r.Application_ID},{r.Activity},{r.administrating_IC}')”
下一个
'或SQL批量插入
端接头
以3442毫秒读取文件。在625毫秒内写入SQL 对于p.Rows中的每个r,在
行中,内存中有实际对象,这些对象的属性包括应用程序ID
、活动
、和管理IC
。它们很容易单独插入,这可能需要一些时间。也可以执行SQL批量插入。将文件中的对象转换为SQL INSERT命令只需不到5秒的时间就可以处理100万行。您可以使用:
Dim xml=XElement.Load(“路径到文件”)
Dim rows=xml。
每行中的每一行
Dim app_id=行..First.Value
Dim活动=行..First.Value
Dim adm_ic=行..第一个值
WriteLine($“应用程序id:{应用程序id}活动{activity},adm_ic:{adm_ic}”)
下一个
这里有一种方法,可以将XML文件拆分为多个片段,并通过SQL Server端的批量加载将每个XML片段插入到DB表中。您可以将SQL打包到存储过程中,并从VB.NET端调用它
SQL
输出
+----+----------------+---------------------------------------------------------------------------------------------------------------------+
|ID |应用程序| ID | xml |片段|
+----+----------------+---------------------------------------------------------------------------------------------------------------------+
|1 | 9238972 | 9238972R01CA|
|2 | 9238973 | 9238973R012CA
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, APPLICATION_ID INT, xml_fragment XML);
;WITH XmlFile (xmlData) AS
(
SELECT TRY_CAST(BulkColumn AS XML)
FROM OPENROWSET(BULK 'e:\Temp\Split XML file into fragments.xml', SINGLE_BLOB) AS x
)
, rs AS
(
SELECT c.value('(APPLICATION_ID/text())[1]','INT') AS [APPLICATION_ID]
, c.query('.') AS [xml_fragment]
FROM XmlFile CROSS APPLY xmlData.nodes('(/PROJECTS/row)') AS t(c)
)
INSERT INTO @tbl (APPLICATION_ID, xml_fragment)
SELECT * FROM rs;
-- test
SELECT * FROM @tbl;
+----+----------------+---------------------------------------------------------------------------------------------------------------------+
| ID | APPLICATION_ID | xml_fragment |
+----+----------------+---------------------------------------------------------------------------------------------------------------------+
| 1 | 9238972 | <row><APPLICATION_ID>9238972</APPLICATION_ID><ACTIVITY>R01</ACTIVITY><ADMINISTERING_IC>CA</ADMINISTERING_IC></row> |
| 2 | 9238973 | <row><APPLICATION_ID>9238973</APPLICATION_ID><ACTIVITY>R012</ACTIVITY><ADMINISTERING_IC>CA</ADMINISTERING_IC></row> |
| 3 | 9238974 | <row><APPLICATION_ID>9238974</APPLICATION_ID><ACTIVITY>R013</ACTIVITY><ADMINISTERING_IC>CA</ADMINISTERING_IC></row> |
+----+----------------+---------------------------------------------------------------------------------------------------------------------+