vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Zippen wie die Profis!  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   RSS-Feeds  | Newsletter  | Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2017
 
zurück
Rubrik: .NET   |   VB-Versionen: VB2005, VB200801.09.09
Klasse zum Loggen in eine ODBC-Tabelle

Mit diesem Klassenmodul lassen sich "fehlerhafte" SQLs in eine Datei speichern und automatisch bei erneutem Aufruf der ExecuteSQL-Methode wieder ausführen, so dass die fehlerhaften SQLs nicht verloren gehen.

Autor:  Carsten StuplichBewertung:     [ Jetzt bewerten ]Views:  7.454 

Wenn man eine Datenbank-Tabelle (ODBC) als „Logdatei“ verwendet, muss man eigentlich nur INSERT-SQLs absenden.

Da es aber durchaus vorkommen kann, dass die Datenbank mal nicht verfügbar ist, sollte man „gescheiterte“ SQLs in einer Datei sichern und später erneut gegen die Datenbank abschicken.

Für diesen Zweck hab ich die Klasse ODBCTableLogger erstellt, die das übergebene SQL auf der Datenbank abschickt und im Fehlerfall in einer Textdatei sichert.
Sobald man erneut ein SQL über die Methode „ExecuteSQL“ ausführt, prüft die Methode, ob fehlerhafte SQLs vorliegen und versucht diese erneut gegen die Datenbank auszuführen. (Alternativ kann auch die Methode „ReexecuteAbortedSQLs“ ausgeführt werden, wenn kein neues SQL abgeschickt werden soll).

Folgenden Code müssen Sie in eine neue Klasse mit dem Namen ODBCTableLogger einfügen:

Imports System.ComponentModel
Imports System.Data.Odbc
Imports System.IO
 
''' <summary>
''' Sendet SQLs (ohne Rückgabewert) an eine ODBC-Datenbank. 
''' Sollte das SQL einen Fehler zürkliefern wird das SQL in einer 
''' Textdate gespeichert und bei erneutem Aufruf der Methode 
''' "ExecuteSQL" ausgeführt.
''' </summary>
''' <remarks></remarks>
Friend Class ODBCTableLogger
 
  Private ODBCConnectionStringValue As String
  Private SQLValue As String
  Private FileForAbortedSQLsValue As String
  Private ReexecuteAbortedSQLsValue As Boolean = True
  Private CommandTimeoutValue As Integer = 60
 
  Private oODBCConnection As Odbc.OdbcConnection
  Private oODBCCommand As Odbc.OdbcCommand
  ''' <summary>
  ''' ODBC Connection String zur Ziel-Datenbank
  ''' </summary>
  Friend Property ODBCConnectionString() As String
    Get
      Return ODBCConnectionStringValue
    End Get
    Set(ByVal value As String)
      ODBCConnectionStringValue = value
    End Set
  End Property
  ''' <summary>
  ''' SQL das ausgeführt werden soll
  ''' </summary>
  Friend Property SQL() As String
    Get
      Return SQLValue
    End Get
    Set(ByVal value As String)
      SQLValue = value
    End Set
  End Property
  ''' <summary>
  ''' Dateiname in der Fehlerhafte SQLs weggeschrieben werden sollen 
  ''' (in ASP.NET muss auch Pfad des des Application-Roots mitgegeben werden!)
  ''' </summary>
  Friend Property FileForAbortedSQLs() As String
    Get
      Return FileForAbortedSQLsValue
    End Get
    Set(ByVal value As String)
      FileForAbortedSQLsValue = value
    End Set
  End Property
  ''' <summary>
  ''' Bestimmt ob fehlerhafte SQL weggeschrieben und neu ausgeführt werden sollen.
  ''' </summary>
  <DefaultValue(True)> _
  Friend Property ReexecuteAbortedSQLs() As Boolean
    Get
      Return ReexecuteAbortedSQLsValue
    End Get
    Set(ByVal value As Boolean)
      ReexecuteAbortedSQLsValue = value
    End Set
  End Property
  ''' <summary>
  ''' Timeout für SQL-Ausführung
  ''' </summary>
  <DefaultValue(60)> _
  Friend Property CommandTimeout() As String
    Get
      Return CommandTimeoutValue
    End Get
    Set(ByVal value As String)
      CommandTimeoutValue = value
    End Set
  End Property
  ''' <summary>
  ''' Initialisiert die Klasse
  ''' </summary>
  ''' <param name="ODBCConnectionString">ODBC-Connection-String 
  ''' zur gewünschten Ziel-Datenbank</param>
  ''' <param name="FileForAbortedSQLs">Datei in der fehlerhafte SQLs für 
  ''' eine erneute Ausführung weggeschrieben werden sollen (bei Aufruf 
  ''' dieser Methode oder der Methode 'CheckForAbortedSQLs'</param>
  ''' <param name="ReexecuteAbortedSQLs">Wenn  True, werden fehlerhafte SQLs 
  ''' weggeschrieben und erneut ausgeführt</param>
  Sub New(ByVal ODBCConnectionString As String, _
    Optional ByVal FileForAbortedSQLs As String = "Error_SQLs.txt", _
    Optional ByVal ReexecuteAbortedSQLs As Boolean = True)
 
    ' Diverse Variablen setzen
    ODBCConnectionStringValue = ODBCConnectionString
    FileForAbortedSQLsValue = FileForAbortedSQLs
    ReexecuteAbortedSQLsValue = ReexecuteAbortedSQLs
 
    oODBCConnection = New Odbc.OdbcConnection(ODBCConnectionStringValue)
  End Sub
  ''' <summary>
  ''' Baut die Connection zur angegebenen Datenbank auf
  ''' </summary>
  Private Sub Connect()
 
    Try
      oODBCConnection.Open()
    Catch ex As Exception
      Throw
    End Try
 
  End Sub
  ''' <summary>
  ''' Führt das angegeben SQL aus.
  ''' </summary>
  ''' <param name="SQL">SQL</param>
  Friend Sub ExecuteSQL(ByVal SQL As String)
 
    Dim lRowsInserted As Long = 0
 
 
    ' SQL für Ausführung bzw. Logging in Fehlerdatei aufbereiten. 
    ' (ungültige Zeichen entfernen)
    SQL = SQL.Replace(Environment.NewLine, " ")
 
    Try
      ' Prüfen ob Connection offen
      If oODBCConnection.State = ConnectionState.Closed Then Connect()
 
      ' Prüfen ob ODBC-Command Object erstellt wurde
      If oODBCCommand Is Nothing Then
        oODBCCommand = New Odbc.OdbcCommand()
        oODBCCommand.CommandTimeout = CommandTimeoutValue
        oODBCCommand.Connection = oODBCConnection
      End If
 
      ' Zu erst prüfen ob noch SQLs in Fehlerdatei liegen
      If ReexecuteAbortedSQLsValue = True Then 
        CheckForAbortedSQLs(FileForAbortedSQLsValue)
      End If
 
      ' SQL ausführen
      With oODBCCommand
        .CommandText = SQL
        lRowsInserted = .ExecuteNonQuery()
      End With
      If lRowsInserted = 0 OrElse lRowsInserted = -1 Then 
        Throw New Exception("Es wurden 0 Datensätze eingefügt/aktualisiert")
      End If
 
    Catch ex As Exception
      ' SQL in Textdatei loggen wenn Option aktiv
      If ReexecuteAbortedSQLsValue = True AndAlso _
        FileForAbortedSQLsValue <> "" AndAlso SQL <> "" Then
 
        WriteLineToFile(FileForAbortedSQLsValue, SQL)
      End If
 
      Throw
    End Try
 
  End Sub
  ''' <summary>
  ''' Schliesst die Verbindung zur Datenbank
  ''' </summary>
  Friend Sub CloseConnection()
 
    Try
      oODBCCommand.Dispose()
      oODBCCommand = Nothing
    Catch ex As Exception
    End Try
 
    Try
      oODBCConnection.Close()
      oODBCConnection.Dispose()
      oODBCConnection = Nothing
    Catch ex As Exception
    End Try
  End Sub
  ''' <summary>
  ''' 'Funktion zum schreiben in sequentielle Datei
  ''' </summary>
  ''' <param name="sFile">Datein inkl. Pfad</param>
  ''' <param name="sText">Text der in die Datei geschrieben werden soll</param>
  ''' <remarks>"Imports System.IO" muss im Modul/Klasse gesetzt sein, 
  ''' in der die Funktion eingefügt wird.</remarks>
  Private Sub WriteLineToFile(ByRef sFile As String, ByRef sText As String)
    On Error GoTo ErrorHandle
 
    Dim objDateiMacher As StreamWriter
    Dim sPath As String = sFile.Substring(0, _
      sFile.Length - (sFile.Length - sFile.LastIndexOf("\")) + 1)
 
    ' Ordner (Pfad) erstellen, falls dieser nicht vorhanden ist
    If sPath <> "" Then
      If Directory.Exists(sPath) = False Then Directory.CreateDirectory(sPath)
    End If
    If File.Exists(sFile) = True Then sText = Environment.NewLine & sText
 
    ' Encoding Angabe ist wichtig damit Umlaute OK sind
    objDateiMacher = New StreamWriter(sFile, True, System.Text.Encoding.Default)
    objDateiMacher.Write(sText)
    objDateiMacher.Close()
    objDateiMacher = Nothing
    Exit Sub
 
ErrorHandle:
 
  End Sub
  ''' <summary>
  ''' Funktion zum schreiben in sequentielle Datei
  ''' </summary>
  ''' <param name="sFile">Datein inkl. Pfad</param>
  ''' <param name="sText"></param>
  ''' <param name="DeletFileIfExist"></param>
  Private Sub WriteFile(ByRef sFile As String, _
    ByRef sText As String, Optional _
    ByVal DeletFileIfExist As Boolean = True)
 
    On Error GoTo ErrorHandle
 
    Dim sPath As String = sFile.Substring(0, _
      sFile.Length - (sFile.Length - sFile.LastIndexOf("\")) + 1)
 
    ' Eventuell vorhandene Datei löschen
    If DeletFileIfExist = True AndAlso File.Exists(sFile) Then File.Delete(sFile)
 
   ' Ordner (Pfad) erstellen, falls dieser nicht vorhanden ist
    If sPath <> "" AndAlso Directory.Exists(sPath) = False Then 
      Directory.CreateDirectory(sPath)
    End If
 
    ' Encoding Angabe ist wichtig damit Umlaute OK sind
    Dim objDateiMacher As StreamWriter = New StreamWriter(sFile, False, _
      System.Text.Encoding.Default)
 
    Using objDateiMacher
      objDateiMacher.Write(sText)
      objDateiMacher.Close()
      objDateiMacher = Nothing
    End Using
    Exit Sub
 
ErrorHandle:
 
  End Sub
  ''' <summary>
  ''' Schaut ob in der Fehlerdatei noch SQL stehen und führt diese aus
  ''' (Diese Funktion wird automatische bei Aufruf der Methode 
  ''' 'ExecuteSQL' ausgeführt, bevor das neue SQL gesendet wird.)
  ''' </summary>
  ''' <param name="sFile">Datei in nach fehlerhaften gesucht werden soll 
  ''' um diese auszuführen.</param>
  Friend Sub CheckForAbortedSQLs(ByVal sFile As String)
 
    If System.IO.File.Exists(sFile) Then
      Dim sErrorSQLs As String = "", lRowsInserted As Long = 0
      Dim oStreamReader As StreamReader = Nothing
 
      Try
        oStreamReader = New StreamReader(sFile, System.Text.Encoding.Default)
        Dim sLine As String = oStreamReader.ReadLine
 
        Do While Not sLine Is Nothing
          ' MessageBox.Show(sLine)
          If sLine <> "" Then
            ' Prüfen ob Connection offen
            If oODBCConnection.State = ConnectionState.Closed Then Connect()
            ' Prüfen ob ODBC-Command Object erstellt wurde
            If oODBCCommand Is Nothing Then
              oODBCCommand = New Odbc.OdbcCommand()
              oODBCCommand.CommandTimeout = CommandTimeoutValue
              oODBCCommand.Connection = oODBCConnection
            End If
 
            ' SQL ausführen
            Try
              ' SQL ausführen
              With oODBCCommand
                .CommandText = sLine
                lRowsInserted = .ExecuteNonQuery()
              End With
              If lRowsInserted = 0 OrElse lRowsInserted = -1 Then 
                Throw New Exception("Es wurden 0 Datensätze eingefügt/aktualisiert")
              End If
            Catch ex As Exception
              ' SQL das erneut nicht ausgeführt werden konnte, in Variable speichern
              If sErrorSQLs <> "" Then sErrorSQLs += Environment.NewLine
              sErrorSQLs += sLine
            End Try
          End If
 
          ' Nächste Zeile festlegen
          sLine = oStreamReader.ReadLine
        Loop
 
        ' Datei wieder schliessen
        If oStreamReader IsNot Nothing Then
          oStreamReader.Close()
          oStreamReader.Dispose()
          oStreamReader = Nothing
        End If
        File.Delete(sFile)
        ' Datei mit übergebliebenen Fehlern neu anlegen (bestehnede Datei wird gelöscht)
        If sErrorSQLs <> "" Then WriteFile(sFile, sErrorSQLs, True)
 
      Catch ex As Exception
      Finally
        ' Datei wieder schliessen
        If oStreamReader IsNot Nothing Then
          oStreamReader.Close()
          oStreamReader.Dispose()
          oStreamReader = Nothing
        End If
      End Try
    End If
  End Sub
End Class

Um nun in eine Tabelle zu loggen benötigen Sie folgende Zeilen:
(Die Werte für den ConnectionString + SQL müssen Sie entsprechend anpassen)

Dim oODBCTableLogger As ODBCTableLogger = _
  New ODBCTableLogger("<ConnectionString>", "Error_SQLs.txt")
 
Try
  oODBCTableLogger.ExecuteSQL("<Insert into ........>")
Catch ex As Exception
Finally
    oODBCTableLogger.CloseConnection()
End Try

Dieser Workshop wurde bereits 7.454 mal aufgerufen.

Über diesen Workshop im Forum diskutieren
Haben Sie Fragen oder Anregungen zu diesem Workshop, können Sie gerne mit anderen darüber in unserem Forum diskutieren.

Neue Diskussion eröffnen

nach obenzurück


Anzeige

Kauftipp Unser Dauerbrenner!Diesen und auch alle anderen Workshops finden Sie auch auf unserer aktuellen vb@rchiv  Vol.6

Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
- nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten
- Symbol-Galerie mit mehr als 3.200 Icons im modernen Look
Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m.
 
   

Druckansicht Druckansicht Copyright ©2000-2017 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel