VB .NET - DataSets und DataTables aus einer XML-Datei in eine SQL Datenbank schreiben

22. Dec 2008 17:01 (bearbeiten)


Ich habe heute nach einer Möglichkeit gesucht, Daten, die ich aus einer SQL Tabelle eines Servers "A" in ein XML-Dataset geschrieben habe, wieder aus diesem XML Dataset zurück in die SQL Tabelle auf dem Server "B" zu schreiben.

Aufgabe war, vier Tabellen von unserem Firmenserver auf die Server draußen bei unseren Mitarbeiter per Programm zu übertragen.

Mein Hauptproblem bei solchen Aufgaben ist eigentlich immer das Erstellen der SQL-Befehle fürs Updaten oder Inserten. Wobei, Problem ist eventuell zu viel gesagt, viel eher nervt es, manuell diese Statements zusammenbauen zu müssen.

Da .NET ja intern über die TableAdapter und DataProvider die Funktion besitzt, eben diese SQL Befehle automatisch zu generieren, dachte ich mir, warum nicht diese Fähigkeit nutzen und mir damit das Getippe und das Prüfen der selbst erstellten SQL Statements zu ersparen.

Die Hauptarbeit in der wichtigsten Funktion ImportTableToSQL übernimmt dabei die Klasse SQLCommandBuilder, die einen DataAdapter mit dem einzutragenden DataSet übergeben bekommt. Anschließend weisen wir dem SQLCommandBuilder für alle Parameter einfach die Werte zu, die in unserem DataSet bereits drin stehen.

Zu guter letzt führen wir den automatisch generierten Insert-Befehl des SQLCommandBuilders aus, et voila, die Tabellen sind aktuell.

Hier der Code, um Daten aus dem SQL-Server in ein XML Dataset zu schreiben. Die wichtigste Stelle hierbei ist Dataset.WriteXML().

  1.  
  2. ''' <summary>
  3. ''' Exports a Table from a SQL Database to a XML file
  4. ''' </summary>
  5. ''' <param name="aSelectStatement">Select Statement for the data which should be exported</param>
  6. ''' <param name="aTableName">Name of the Table (needed for creating the filename)</param>
  7. ''' <param name="aOutputXMLDirectory">Ausgabe-Verzeichnis</param>
  8. ''' <param name="aOutputXMLFilename">Ausgabe-Dateiname ohne Dateiendung und ohne Pfadangabe</param>
  9. ''' <param name="aDatasetName"></param>
  10. ''' <param name="Append">An bestehende XML-Datei anhängen (INFER-Modus)</param>
  11. ''' <remarks></remarks>
  12. Public Shared Sub ExportTable(ByVal strCon As String, _
  13. ByVal aSelectStatement As String, _
  14. ByVal aTableName As String, _
  15. ByVal aOutputXMLDirectory As String, _
  16. Optional ByVal aOutputXMLFilename As String = "", _
  17. Optional ByVal aDatasetName As String = "NewDataSet", _
  18. Optional ByVal CreateSchemaFiles As Boolean = False, _
  19. Optional ByVal Append As Boolean = False)
  20.  
  21. Using con As SqlClient.SqlConnection = New SqlClient.SqlConnection(strCon)
  22.  
  23. Try
  24. con.Open()
  25. Dim ds As New DataSet(aDatasetName)
  26. Dim da As SqlClient.SqlDataAdapter = New SqlClient.SqlDataAdapter(aSelectStatement, con)
  27.  
  28. da.FillSchema(ds, SchemaType.Source, aTableName)
  29. da.Fill(ds, aTableName)
  30.  
  31. ' Create Filename
  32. Dim strFullFilename As String
  33.  
  34. ' Trailing backslash?
  35. If Not aOutputXMLDirectory.EndsWith("\") Then aOutputXMLDirectory += "\"
  36.  
  37. ' Create dir
  38. If Not System.IO.Directory.Exists(aOutputXMLDirectory) Then
  39. System.IO.Directory.CreateDirectory(aOutputXMLDirectory)
  40. End If
  41.  
  42. ' Filename given?
  43. If aOutputXMLFilename = "" Then
  44. If aTableName = "" Then
  45. aTableName = My.Computer.FileSystem.GetTempFileName
  46. End If
  47. aOutputXMLFilename = aTableName
  48. End If
  49.  
  50. ' Create filename
  51. strFullFilename = aOutputXMLDirectory & aOutputXMLFilename
  52.  
  53. ' If XML-File already exists use it and add information to it
  54. If Append Then
  55. If System.IO.File.Exists(strFullFilename & ".XML") Then
  56. ds.ReadXml(strFullFilename & ".XML", XmlReadMode.InferSchema)
  57. End If
  58. End If
  59.  
  60. ' Write XML
  61. ds.WriteXml(strFullFilename & ".XML")
  62.  
  63. ' Write Schema?
  64. If CreateSchemaFiles Then ds.WriteXmlSchema(strFullFilename & ".XSD")
  65.  
  66. ' Done
  67. Catch ex As Exception
  68. Debug.Print(ex.message)
  69. End Try
  70.  
  71. End Using
  72. End Sub
  73.  

Die folgende Funktion durchsucht ein Verzeichnis nach XML- und XSD-Dateien. Aus den gefundenen Dateien wird ein Dataset erstellt und dies weiter an die Prozedur ImportDatasetToSQL gegeben.

  1.  
  2. ''' <summary>
  3. ''' Importiert Daten aus XML Dateien in eine SQL Server Tabelle
  4. ''' </summary>
  5. ''' <param name="aXMLSourceDirectory">Quellverzeichnis der XML-Dateien, die importiert werden sollen</param>
  6. ''' <param name="aSQLConnectionString">SQL Verbindungsstring</param>
  7. ''' <remarks></remarks>
  8. Public Shared Sub ImportTablesToSQL(ByVal aXMLSourceDirectory As String, ByVal aSQLConnectionString As String)
  9.  
  10. Dim filters As String() = {"*.XML"}
  11.  
  12. Dim lstFiles As System.Collections.ObjectModel.ReadOnlyCollection(Of String) = _
  13. My.Computer.FileSystem.GetFiles(aXMLSourceDirectory, FileIO.SearchOption.SearchAllSubDirectories, filters)
  14.  
  15. For Each fn As String In lstFiles
  16.  
  17. Dim ds As New DataSet
  18.  
  19. Try
  20.  
  21. ' Read the schema
  22. ' Filename is the same as the xml file except its extension
  23. ds.ReadXmlSchema(fn.Replace(".XML", ".XSD"))
  24.  
  25. ' Read the XML File
  26. ds.ReadXml(fn)
  27.  
  28. 'For Each tbl As DataTable In ds.Tables
  29. ' Debug.Print("Table: " & tbl.TableName)
  30. ' For Each cc As System.Data.Constraint In tbl.Constraints
  31. ' Debug.Print("Constraint: " & cc.ConstraintName)
  32. ' Next
  33. ' For Each pkcol As DataColumn In tbl.PrimaryKey
  34. ' Debug.Print("Primary Key: " & pkcol.ColumnName)
  35. ' Next
  36. 'Next
  37.  
  38. ImportDatasetToSQL(ds, aSQLConnectionString)
  39.  
  40. Catch ex As Exception
  41. Debug.Print(ex.Message)
  42. Continue For
  43. End Try
  44.  
  45. Next
  46.  
  47. End Sub
  48.  

Diese Funktion importiert jede Tabelle des Datasets in die SQL-Tabelle mit dem selben Namen.

  1.  
  2. Private Shared Sub ImportDatasetToSQL(ByRef aDataset As DataSet, ByVal aSQLConnectionString As String)
  3.  
  4. Using con As New SqlClient.SqlConnection(aSQLConnectionString)
  5.  
  6. Try
  7. con.Open()
  8. Catch ex As Exception
  9. Debug.Print(ex.Message)
  10. Exit Sub
  11. End Try
  12.  
  13. Try
  14.  
  15. For Each tbl As DataTable In aDataset.Tables
  16. ImportTableToSQL(tbl, con)
  17. Next
  18.  
  19. Catch ex As Exception
  20. Debug.Print(ex.Message)
  21. End Try
  22.  
  23. con.Close()
  24. End Using
  25.  
  26. End Sub
  27.  

Hier nun die eigentliche Import-Funktion.

Wir übergeben hier ein DataTable und einen SQL Connectionstring. Im DataTable sind die Werte drin, die in die SQL Datenbank geschrieben werden sollen.

  1.  
  2. Private Shared Sub ImportTableToSQL(ByRef aDataTable As DataTable, ByRef aConnection As SqlClient.SqlConnection)
  3.  
  4. ' Create a command for the DataAdapter
  5. Dim cmd As New SqlClient.SqlCommand("Select * From " & aDataTable.TableName, aConnection)
  6.  
  7. ' Create the DataAdapter (needed for creating the sql-statement)
  8. Dim da As New SqlClient.SqlDataAdapter(cmd)
  9.  
  10. ' Fill our DataAdapter with Data from our DataTable
  11. da.FillSchema(aDataTable, SchemaType.Source)
  12. da.Fill(aDataTable.DataSet, aDataTable.TableName)
  13.  
  14. ' Create the SQL Command Builder
  15. Dim cb As New SqlClient.SqlCommandBuilder(da)
  16. cb.SetAllValues = False
  17.  
  18. ' Go thru all rows and insert the data
  19. For Each r As DataRow In aDataTable.Rows
  20.  
  21. ' Create the Insert-Command
  22. Dim cmdResult As New SqlClient.SqlCommand(cb.GetInsertCommand.CommandText, aConnection)
  23. cmdResult.Parameters.Clear()
  24.  
  25. Dim i As Integer = 0
  26.  
  27. ' Go thru all columns in our DataTable and create a SQLParameter for our Statement with the value
  28. ' from our DataTable.
  29. For Each col As DataColumn In aDataTable.Columns
  30. i += 1
  31. ' cmdResult.Parameters.Add("@p" & i, col.DataType).Value = r.Item(col.ColumnName)
  32. cmdResult.Parameters.AddWithValue("@p" & i, r.Item(col.ColumnName))
  33. Next
  34.  
  35. Debug.Print("ImportTableToSQL: " & cmdResult.CommandText)
  36.  
  37. Dim iAffectedRecords As Integer = cmdResult.ExecuteNonQuery()
  38. Debug.Print("Records Affected: " & iAffectedRecords)
  39.  
  40. Next
  41.  
  42. End Sub
  43.  

Achja, wie immer gilt, gerne darf man mir Verbesserungen, Anregungen und natürlich auch Kritik zukommen lassen.

2 Antworten zu “VB .NET - DataSets und DataTables aus einer XML-Datei in eine SQL Datenbank schreiben”

  1. Susanne

    Vielen herzlichen Dank für die Bereitstellung des Codes. Das hat meinen Tag so richtig gut gemacht!!!! Ich bin ein SQL-Server und XMl-Neuling.
    Es sind die stillen Teamworker im Internet, die einem das Leben vereinfachen. Vielen, vielen Dank!!!

  2. dahead

    Hallo Susanne,

    freut mich sehr, dass dir der Code geholfen hat.

    Vielen Dank für dein Feedback!

    Gruß,
    dh

Eine Antwort hinterlassen