VB Programm schreibt in SQL Datenbank

  • VB.NET

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von Trade.

    VB Programm schreibt in SQL Datenbank

    Moin Leute, hab gerade ein "kleines" Programm auf dem Prüfstand welches Daten in die SQL Datenbank schreibt. Das funktioniert auch!Nur leider ist es total langsam!!!! D.h. es werden ungefähr 1 - 2 Datensätze in der Sekunde geschrieben:Ich versuche mal kurz zu erläutern wie mein Programm aufgebaut ist:Der IO Reader liest die Daten aus einer CSV Datei:
    Logmessage zeigt mir in einer *.txt wie lange das dauert. Also in einer Sekunde ungefähr 35 Datensätze

    VB.NET-Quellcode

    1. 'Datei wird eingebunden mit entsprechender Codierung
    2. LogMessage("__IOREADER " & TimeOfDay & " anfang")
    3. Using ioReader As New Microsoft.VisualBasic.FileIO.TextFieldParser(einzeldatei, System.Text.Encoding.GetEncoding("ISO-8859-1"))
    4. 'delimiter wird eingerichtet
    5. ioReader.TextFieldType = FileIO.FieldType.Delimited
    6. 'delimiter Zeichen
    7. ioReader.SetDelimiters(",")
    8. 'Solange die Daten nicht leer sind
    9. While Not ioReader.EndOfData
    10. LogMessage("__IOREADER " & TimeOfDay & " anfang")
    11. 'lese aktuelle Line und springe 1 Zeile weiter
    12. ioReader.ReadLine()
    13. 'Beginne ab Zeile 3
    14. If ioReader.LineNumber > 2 Then
    15. 'schreibe ins Array die Werte
    16. arrcurrentrow = ioReader.ReadFields()
    17. übertragung()
    18. LogMessage("__IOREADER " & TimeOfDay & " ENDE")
    19. Else
    20. End If
    21. End While
    22. End Using


    Jetzt werden die Daten aufbereitet und in die jeweiligen Variablen geschrieben und anschließend auf unseren SQL hochgeladen.
    Das Senden der SQL Befehle geht auch fix. Auch rund 30 Datensätze pro Sekunde.

    VB.NET-Quellcode

    1. Dim dtrs As DataTable
    2. 'Zeit wird umformatiert / geparst
    3. Dim datum As DateTime
    4. datum = arrcurrentrow(0)
    5. Date.TryParseExact(datum, "dd.MM.yyyy HH:mm:ss", Globalization.CultureInfo.CurrentCulture, Globalization.DateTimeStyles.None, dtUHRZEIT)
    6. 'LogMessage("sql übertragung " & TimeOfDay & " anfang")
    7. 'Datenarray wird in Variablen gespeichert
    8. UHRZEIT = Format(dtUHRZEIT, "yyyyMMddHHmmss")
    9. USERNAME = arrcurrentrow(1)
    10. iANZAHL_SEITEN = arrcurrentrow(2)
    11. copies = arrcurrentrow(3)
    12. strDRUCKERNAME = arrcurrentrow(4)
    13. strdocumentname = arrcurrentrow(5)
    14. strclient = arrcurrentrow(6)
    15. strpapersize = arrcurrentrow(7)
    16. strlanguage = arrcurrentrow(8)
    17. duplex = arrcurrentrow(11)
    18. strgrayscale = arrcurrentrow(12)
    19. strsize = arrcurrentrow(13)
    20. If duplex = "NOT DUPLEX" Then
    21. intduplex = 0
    22. Else
    23. intduplex = 1
    24. End If
    25. If strgrayscale = "NOT GRAYSCALE" Then
    26. intgrayscale = 0
    27. Else
    28. intgrayscale = 1
    29. End If
    30. If strsize.ToLower.Contains("kb") Then
    31. strsize = strsize.ToLower.Replace("kb", "")
    32. ElseIf strsize.ToLower.Contains("mb") Then
    33. strsize = strsize.ToLower.Replace("mb", "")
    34. End If
    35. If strdocumentname.ToLower.Contains("'") Then
    36. strdocumentname = strdocumentname.ToLower.Replace("'", "''")
    37. End If
    38. 'Schreibe Variablen in Datensatz für Klasse clsDatensatz
    39. Dim Datensatz As New clsDatensatz
    40. Datensatz.UHRZEIT = UHRZEIT
    41. Datensatz.USERNAME = If(USERNAME.Length < 50, USERNAME, USERNAME.Substring(0, 50))
    42. Datensatz.ANZAHL_SEITEN = iANZAHL_SEITEN
    43. Datensatz.copies = copies
    44. Datensatz.DRUCKERNAME = If(strDRUCKERNAME.Length < 50, strDRUCKERNAME, strDRUCKERNAME.Substring(0, 50))
    45. Datensatz.dokumentname = If(strdocumentname.Length < 100, strdocumentname, strdocumentname.Substring(0, 100))
    46. Datensatz.client = If(strclient.Length < 20, strclient, strclient.Substring(0, 20))
    47. Datensatz.papersize = If(strpapersize.Length < 5, strpapersize, strpapersize.Substring(0, 5))
    48. Datensatz.language = If(strlanguage.Length < 25, strlanguage, strlanguage.Substring(0, 25))
    49. Datensatz.duplex = intduplex
    50. Datensatz.FARBCODE = intgrayscale
    51. Datensatz.size = strsize
    52. lstDatensatz.Add(Datensatz)
    53. 'LogMessage("sql übertragung " & TimeOfDay & " ende")
    54. 'Für jeden Datensatz
    55. For Each ocelot As clsDatensatz In lstDatensatz
    56. 'LogMessage("sql insert " & ocelot.USERNAME & " " & ocelot.UHRZEIT & " anfang")
    57. sql = "select * from printlog where username = '" & ocelot.USERNAME & "' and uhrzeit = '" & ocelot.UHRZEIT & "' and druckername = '" & ocelot.DRUCKERNAME & "'"
    58. dtrs = DoSQLQuery(sql, dateiname)
    59. If dtrs.Rows.Count = 0 Then
    60. 'Datensatz schreiben
    61. '("Der rote Text sind die Spaltennamen in der SQL-Datenbank. DIESE MÜSSEN IDENTISCH heißen wie in der SQL-Datenbank. Das Schwarze sind die Einträge"
    62. sql = "insert into printlog " & "(uhrzeit, username, anzahl_seiten, copies, documentname, druckername, clientname, papersize, driver, duplex, grayscale, printsizes) " &
    63. "values ('" & ocelot.UHRZEIT & "', '" & ocelot.USERNAME & "', " & ocelot.ANZAHL_SEITEN & ", " & ocelot.copies & ", '" & ocelot.dokumentname & _
    64. "', '" & ocelot.DRUCKERNAME & "', '" & ocelot.client & "', '" & ocelot.papersize & "', '" & ocelot.language & "', " & ocelot.duplex & ", " & _
    65. ocelot.FARBCODE & ", " & ocelot.size & ")"
    66. Try
    67. DoSQLExecute(sql)
    68. Catch ex As Exception
    69. SendeMail("Printlogger meldet: Fehler Datenbankzugriff nicht möglich", "Fehler beim Hochladen der Datei " & dateiname & vbCrLf & sql & vbCrLf & ex.Message & vbCrLf & vbCrLf & "Das Programm wurde beendet.", {"xxxxxxxxxxxxxxxxx@xxxxxxxxxxx.com"}, "Hardcore-Print@xxxxxxxxxx.com", "HardcorePrint")
    70. killswitch()
    71. End Try
    72. Else
    73. End If
    74. 'LogMessage("sql insert ende " & ocelot.USERNAME & " " & ocelot.UHRZEIT & " ende")
    75. Next
    76. End Sub


    Keine Ahnung warum das Programm so langsam ist... erkennt evtl. jemand den Flaschenhals?

    Gruß

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Trade“ ()

    Sry aber so unformatiert erkenne ich gar nix.
    There is no CLOUD - just other people's computers

    Q: Why do JAVA developers wear glasses?
    A: Because they can't C#

    Daily prayer:
    "Dear Lord, grand me the strength not to kill any stupid people today and please grant me the ability to punch them in the face over standard TCP/IP."
    Wahrscheinlich öffnest Du und schließt Du die Verbindung zur Datenbank in Deinen hier nicht für uns ersichtlichen Functions / Subs "DoSQLQuery" und "DoSQLExecute" immer wieder.

    Dies muss dann langsam sein - einmal Verbindung öffnen und nach getaner Arbeit wieder schließen.

    Jedenfalls ist nirgends in Deinem (leider nicht formatierten Code) ein Connection.Open sichtbar, da kann man nur so wie ich nun raten!

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Thias“ ()

    Danke für die Antworten!

    Sorry für den Code...
    Hier der SQL Reader^^

    VB.NET-Quellcode

    1. Imports System.Data.SqlClient
    2. Module mdlSQLReader
    3. Dim strConnectionString As String = "Server=xxxx\SQLEXPRESS2012;database=xxxx;User ID=sqlazubi;Password=xxxxx!5;Application Name=MyApp"
    4. Function DoSQLQuery(ByVal sql As String, ByVal dateiname As String) As DataTable
    5. DoSQLQuery = New DataTable
    6. Using con As New SqlConnection(strConnectionString)
    7. Try
    8. con.Open()
    9. Using com As New SqlCommand(sql, con)
    10. Using RDR As SqlDataReader = com.ExecuteReader()
    11. DoSQLQuery.Load(RDR)
    12. End Using
    13. End Using
    14. con.Close()
    15. Catch ex As Exception
    16. SendeMail("Printlogger meldet: Fehler Datenbankzugriff nicht möglich", ex.Message & vbCrLf & vbCrLf & "Das Programm wurde beendet.", {xxxxx@xxxxxx.com"}, "Hardcore-Print@xxxxxx.com", "HardcorePrint")
    17. killswitch()
    18. End Try
    19. End Using
    20. End Function
    21. Sub DoSQLExecute(ByVal sql As String)
    22. Dim com As New SqlCommand
    23. Dim adapter As New SqlClient.SqlDataAdapter
    24. Using con As New SqlConnection(strConnectionString)
    25. con.Open()
    26. com.Connection = con
    27. com.CommandText = sql
    28. com.ExecuteNonQuery()
    29. con.Close()
    30. End Using
    31. End Sub
    32. End Module

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Trade“ ()

    Versuch es mal so:

    VB.NET-Quellcode

    1. Imports System.Data.SqlClient
    2. Module mdlSQLReader
    3. Private con As New SqlConnection("Server=xxxx\SQLEXPRESS2012;database=xxxx;User ID=sqlazubi;Password=xxxxx!5;Application Name=MyApp")
    4. Function DoSQLQuery(ByVal sql As String, ByVal dateiname As String) As DataTable
    5. DoSQLQuery = New DataTable
    6. Try
    7. con.Open()
    8. Using com As New SqlCommand(sql, con)
    9. Using RDR As SqlDataReader = com.ExecuteReader()
    10. DoSQLQuery.Load(RDR)
    11. End Using
    12. End Using
    13. con.Close()
    14. Catch ex As Exception
    15. SendeMail("Printlogger meldet: Fehler Datenbankzugriff nicht möglich", ex.Message & vbCrLf & vbCrLf & "Das Programm wurde beendet.", {"alexander.wohlschlaeger@esmo-ag.com"}, "Hardcore-Print@esmo-ag.com", "HardcorePrint")
    16. killswitch()
    17. End Try
    18. End Function
    19. Sub DoSQLExecute(ByVal sql As String)
    20. Dim com As New SqlCommand
    21. Dim adapter As New SqlClient.SqlDataAdapter
    22. con.Open()
    23. com.Connection = con
    24. com.CommandText = sql
    25. com.ExecuteNonQuery()
    26. con.Close()
    27. End Sub
    28. End Module
    There is no CLOUD - just other people's computers

    Q: Why do JAVA developers wear glasses?
    A: Because they can't C#

    Daily prayer:
    "Dear Lord, grand me the strength not to kill any stupid people today and please grant me the ability to punch them in the face over standard TCP/IP."
    Sag ich - doch - mein Raten war richtig - bei jedem Insert wird die Verbingung zur Datenbank erst geöffnet und sofort wieder geschlossen.

    Das con.Open gehört aber vor die "For-Schleife":

    VB.NET-Quellcode

    1. For Each ocelot As clsDatensatz In lstDatensatz

    und das Con.Close dann nach

    VB.NET-Quellcode

    1. End For


    Und bitte Deinen Code mit [ vbnet ] und [ /vbnet ] umschließen (ohne die Leerzeichen nach / vor der eckigen Klammer)!

    Die Con.open und Con.Close dann an den bisherigen Stellen entfernen und Deine erstellte Connection mit als Parameter mitübergeben!

    Bzw. natürlich eine Funktion schreiben, welche Dir eine Connection erstellt und zurückgibt.


    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Thias“ ()

    Ich würde dir empfehlen dir mal die typisierten Datasets anzusehen.

    Da muss man sich auch nicht groß um das Öffnen / schließen von Verbindungen kümmern. Einfach alle neuen Datensätze ins dataset rein und dann per update Befehl in einem Rutsch auf den Server. Das ist viel einfacher zu Programmieren und zudem wahrscheinlich viel schneller als dein Lösungsansatz

    Sieh dir das mal an:
    erfinderdesrades.unitweb.de/Pr…r/Downloadpage/index.html
    das hilft :)

    PS: Klar ein Bulk import ist schneller aber bringt auch einige Schwierigkeiten mit sich zb. das die entsprechende Datei die importiert werden soll auf dem gleichen Host wie der SQLServer liegen muss und das ein bulk import ab 10 Fehler einfach die komplette Datei ignoriert (sicher kann man das auch irgendwo einstellen aber ich für meinen Teil finde es angenehmer wenn man dann Programmtechnisch die Fehler handlen kann)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Cell“ ()

    zb. das die entsprechende Datei die importiert werden soll auf dem gleichen Host wie der SQLServer liegen muss

    Diese Aussage ist leider faslch - siehe z.B.: dotnetcurry.com/ShowArticle.aspx?ID=323

    Bei einem Kunden befülle ich ca. alle 6 Monate eine Tabelle mit ca. 10 Millionen-Datensäzen - zuerst immer in einer Schleife 100.000 Datensätze aus 10 lokalen csv-Dateien ( zusammen ca. 5GB groß) in eine DataTable einlesen -
    und dann mit sqlbulkcopy.WriteToServer(DataTable) (siehe Link) die Daten auf den SQL-Server schieben - in 15 Minuten ist alles erledigt!

    Selbstvertändlich ist der lokale PC (16GB RAM) und der SQL-Server sehr gut mit Hauptspeicher bestückt!

    DataSets sollte @danielwonst sich aber natürlich unabhängig davon ansehen!

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „Thias“ ()

    Diese Aussage ist leider faslch - siehe z.B.: dotnetcurry.com/ShowArticle.aspx?ID=323​


    Vielleicht habe ich meinen Beitrag etwas unglücklich formuliert. Ich kenne mich bei weitem nicht gut genug mit dem MSSQL aus um sichergehen zu können das ich nicht eine Option übersehen habe (oder mehrere) ich selbst nutze in der Firma auch BulkCopy um mehrere Millionen Datensätze pro Tag in den MSSQL zu packen. Ich habe es allerdings nicht hinbekommen die Daten direkt von einem anderen Rechner im Netzwerk zu laden. In meinem Szenario habe ich das Problem umgangen indem ich die Dateien erst auf den Server kopiere, dann einlese und anschließend lösche.
    @danielwonst Es gibt einen entsprechenden VB.NET-Codetag, den Du mit ​[vbnet][/vbnet] benutzen kannst, damit die Syntax gehighlighted wird. Ich habe die Formatierung jetzt mal für Dich angepasst.
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!: