如何使用 XmlReader 将 xml 文档中的多行插入到 sql 服务器

How to insert multiple rows from xml document to sql server using XmlReader

当然,我用谷歌搜索了我的问题:"visual basic xml to sql how to insert many rows XmlReader"。我什至将 'many' 更改为 'multiple'.

到目前为止,我只能将 first 条目添加到我的数据库中。 我很高兴能够使用 XmlReader,因为我听说它非常高效。 我也很高兴能够使用参数,因为无论如何我都无法正确连接(是的,我喜欢优雅地编码 - 我不会在这里谈论我的衣服)。

我的VB.Net代码:

Imports System.Data.SqlClient
Imports System.Xml

Public Class Form1
Private Sub ButtonOK_Click(sender As Object, e As EventArgs) Handles ButtonOK.Click        
    Dim xmlFile As String           
    Dim connectionString As String  
    Dim connection As SqlConnection 
    Dim command As SqlCommand       
    Dim ds As New DataSet           
    Dim reader As XmlReader         
    Dim sqlStatement As String      

    'Tag names inside xml document, will have to be inserted into table
    Dim company As Integer
    Dim name As String
    Dim streetaddress As String
    Dim city As String        
    Dim status As Char

    connectionString = "this connection string works"
    xmlFile = "MyXMLFile.xml"
    connection = New SqlConnection(connectionString)
    reader = XmlReader.Create(xmlFile, New XmlReaderSettings())
    ds.ReadXml(reader)

    Dim doc As New XmlDocument()
    doc.Load(xmlFile)
    Dim nodelist As XmlNodeList = doc.SelectNodes(".//siteelement/site")
    For Each node As XmlElement In nodelist

        Dim i As Integer
        For i = 0 To ds.Tables(0).Rows.Count - 1
            company = Convert.ToInt32(ds.Tables(0).Rows(i).Item(0))                
            name = ds.Tables(0).Rows(i).Item(1)
            streetaddress = ds.Tables(0).Rows(i).Item(2)                
            city = ds.Tables(0).Rows(i).Item(3)                
            status = ds.Tables(0).Rows(i).Item(4)

            sqlStatement = "INSERT INTO [dbo].[SITE] ([COMPANY], [NAME], [STREETADDRESS], [CITY], [STATUS])" &
            "VALUES (@COMPANY, @NAME, @STREETADDRESS, @CITY, @STATUS)"
            command = New SqlCommand(sqlStatement, connection)
            command.Parameters.AddWithValue("@COMPANY", company)                
            command.Parameters.AddWithValue("@NAME", name)
            command.Parameters.AddWithValue("@STREETADDRESS", streetaddress)
            command.Parameters.AddWithValue("@CITY", city)                
            command.Parameters.AddWithValue("@STATUS", status)
            Try
                connection.Open()
                Dim rowsAffected As Integer = command.ExecuteNonQuery()
                MessageBox.Show(rowsAffected & " entries were inserted into Site table")
                'Release the resources
                command.Dispose()
            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try
            'Execute the sql statement against the connection
            command.ExecuteNonQuery()
        Next
    Next
    connection.Close()
End Sub
End Class

我的 xml 文件是什么样的:

<?xml version="1.0" encoding="UTF-8"?>
<siteelement>
<site>
  <company>1000</company>   
  <name>STORE #2336</name>
  <streetAddress>123 London Calling</streetAddress> 
  <city>London</city>   
  <status>I</status>
</site>

<site>
  <company>1001</company>   
  <name>STORE #2332</name>
  <streetAddress>123 City of New Orleans</streetAddress>    
  <city>New Orleans</city>  
  <status>A</status>
</site>

<site>
  <company>1002</company>   
  <name>STORE #2333</name>
  <streetAddress>123 Bla bla bla</streetAddress>
  <city>Somewhere</city>    
  <status>A</status>
</site>
</siteelement>

问题:如何让 reader 通读所有 xml 文档?我错过了什么?哪里不对?

任何帮助将不胜感激。请注意我是 Visual Basic 的新手(不到一周!),如果您认为我可以改进我的代码...

提前致谢。

在循环的第一次迭代中,您将打开 SqlConnection,但永远不会关闭它。然后,在循环的下一次迭代中,您试图再次打开 SqlConnection,由于连接已经打开,这会引发以下异常:

The connection was not closed. The connection's current state is open.

我对您的代码做了一些小改动,以演示处理 SqlConnection(或实现 IDisposable 接口的任何其他对象)的正确方法。

Dim xmlFile As String
Dim connectionString As String
Dim ds As New DataSet
Dim reader As XmlReader
Dim sqlStatement As String

'Tag names inside xml document, will have to be inserted into table
Dim company As Integer
Dim name As String
Dim streetaddress As String
Dim city As String
Dim status As Char

connectionString = "this connection string works"
xmlFile = "MyXMLFile.xml"
reader = XmlReader.Create(xmlFile, New XmlReaderSettings())
ds.ReadXml(reader)

Dim doc As New XmlDocument()
doc.Load(xmlFile)
Dim nodelist As XmlNodeList = doc.SelectNodes(".//siteelement/site")
For Each node As XmlElement In nodelist

    Dim i As Integer
    For i = 0 To ds.Tables(0).Rows.Count - 1
        company = Convert.ToInt32(ds.Tables(0).Rows(i).Item(0))
        name = ds.Tables(0).Rows(i).Item(1)
        streetaddress = ds.Tables(0).Rows(i).Item(2)
        city = ds.Tables(0).Rows(i).Item(3)
        status = ds.Tables(0).Rows(i).Item(4)

        sqlStatement = "INSERT INTO [dbo].[SITE] ([COMPANY], [NAME], [STREETADDRESS], [CITY], [STATUS]) VALUES (@COMPANY, @NAME, @STREETADDRESS, @CITY, @STATUS)"

        Using connection As New SqlConnection(connectionString)
            Using command As New SqlCommand(sqlStatement, connection)
                command.Parameters.AddWithValue("@COMPANY", company)
                command.Parameters.AddWithValue("@NAME", name)
                command.Parameters.AddWithValue("@STREETADDRESS", streetaddress)
                command.Parameters.AddWithValue("@CITY", city)
                command.Parameters.AddWithValue("@STATUS", status)
                Try
                    connection.Open()
                    Dim rowsAffected As Integer = command.ExecuteNonQuery()
                    Console.WriteLine(rowsAffected & " entries were inserted into Site table")
                    'Release the resources
                    command.Dispose()
                Catch ex As Exception
                    Console.WriteLine(ex.Message)
                End Try
                'Execute the sql statement against the connection
                command.ExecuteNonQuery()

            End Using
        End Using

    Next
Next

您会注意到我将您的 SqlConnectionSqlCommand 包装在一个看起来很有趣的 Using 块中,而不是使用 Dim 关键字。 Using 块的目的是确保在到达 Using 块末尾时正确处理所有资源。

所以在我的代码示例中,SQLConnection 对象在循环的每次迭代中被完全销毁并重新创建,因此 connection.Open() 语句对每次迭代都有效。

显然在每次迭代时销毁并重新创建一个新的 SqlConnection 并不是最有效的方法,但我不想过多修改您的代码,因为您说您仍在学习。

或者,您可以简单地添加一行代码来关闭连接,例如 connection.Close(),但我认为这展示了更好的编码实践。