如何使用XmlReader从xml文档向sql server插入多行

时间:2017-07-12 16:31:04

标签: xml vb.net xmlreader

当然,我google了我的问题:" visual basic xml to sql如何插入多行XmlReader"。我甚至改变了许多'到多个'。

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

我的VB.Net代码:

mkdir /arango-data
chmod 777 /arango-data
sed -i.bak 's/^\(directory = \).*/\1\/arango-data/' /etc/arangodb3/arangod.conf

我的xml文件是什么样的:

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文档?我错过了什么?什么是不正确的?

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

提前致谢。

1 个答案:

答案 0 :(得分:0)

在循环的第一次迭代中,您打开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(),但我觉得这表明更好的编码实践。