2018-12-14 16:18:12 +01:00

305 lines
11 KiB
VB.net

Imports FirebirdSql.Data.FirebirdClient
Imports System.Text.RegularExpressions
Imports DigitalData.Modules.Logging
''' <summary>
''' MODULE: Firebird
'''
''' VERSION: 0.0.0.4
'''
''' DATE: 05.12.2018
'''
''' DESCRIPTION:
'''
''' DEPENDENCIES: NLog, >= 4.5.10
'''
''' EntityFramework.Firebird, >= 6.4.0
'''
''' FirebirdSql.Data.FirebirdClient, >= 6.4.0
'''
''' PARAMETERS: LogConfig, DigitalData.Modules.Logging.LogConfig
''' The LogFactory containing the current log config. Used to instanciate the class logger for this and any dependent class
'''
''' DataSource, String
''' The server where the database lives, for example 127.0.0.1 or dd-vmx09-vm03
'''
''' Database, String
''' The location of the Database in the format `127.0.0.1:E:\Path\To\Database.FDB`
'''
''' User, String
''' The user name to connect as
'''
''' Password, String
''' The user's password
'''
''' PROPERTIES: ConnectionEstablished, Boolean
''' If the last opened connection was successful
'''
''' ConnectionFailed, Boolean
''' If the last opened connection failed
'''
''' ConnectionString, String
''' The used connectionstring
'''
''' EXAMPLES:
'''
''' REMARKS: If the connection fails due to "wrong username or password", the cause might be that the server harddrive is full..
''' </summary>
Public Class Firebird
Private _logger As Logger
Private _logConfig As LogConfig
Private _connectionServer As String
Private _connectionDatabase As String
Private _connectionUsername As String
Private _connectionPassword As String
Private _connectionString As String
Public Enum TransactionMode
NoTransaction
WithTransaction
End Enum
Public ReadOnly Property ConnectionString As String
Get
Return _connectionString
End Get
End Property
Public ReadOnly Property DatabaseName As String
Get
Dim oRegex As New Regex("^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:")
Dim oPath As String = oRegex.Replace(_connectionDatabase, "")
Dim oFileInfo As New IO.FileInfo(oPath)
Return oFileInfo.Name
End Get
End Property
''' <summary>
'''
''' </summary>
''' <param name="Datasource"></param>
''' <param name="Database"></param>
''' <param name="User"></param>
''' <param name="Password"></param>
''' <exception cref="Exceptions.DatabaseException"></exception>
Public Sub New(LogConfig As LogConfig, Datasource As String, Database As String, User As String, Password As String)
_logger = LogConfig.GetLogger()
_logConfig = LogConfig
Dim oConnectionString = GetConnectionString(Datasource, Database, User, Password)
_connectionServer = Datasource
_connectionDatabase = Database
_connectionUsername = User
_connectionPassword = Password
_connectionString = oConnectionString
_logger.Debug("Connecting to database..")
' Test the connection
Dim oConnection = GetConnection()
' If initial connection was successfully, close it
oConnection?.Close()
If oConnection Is Nothing Then
Throw New Exceptions.DatabaseException()
End If
_logger.Debug("Connection sucessfully established!")
End Sub
Public Function GetConnection() As FbConnection
Try
Dim oConnection = New FbConnection(_connectionString)
oConnection.Open()
Return oConnection
Catch ex As Exception
_logger.Error(ex)
Return Nothing
End Try
End Function
''' <summary>
''' Builds a connectionstring from the provided arguments.
''' </summary>
''' <param name="DataSource">The database server where to connect to</param>
''' <param name="Database">The datasource, eg. the path of the FDB-file</param>
''' <param name="User">The user used to connect to the database</param>
''' <param name="Password">The password of the connecting user</param>
''' <returns>A connectionstring</returns>
Private Function GetConnectionString(DataSource As String, Database As String, User As String, Password As String) As String
Return New FbConnectionStringBuilder With {
.DataSource = DataSource,
.Database = Database,
.UserID = User,
.Password = Password
}.ToString()
End Function
Private Function MaybeGetTransaction(Connection As FbConnection, Mode As TransactionMode)
If Mode = TransactionMode.NoTransaction Then
Return Nothing
ElseIf TransactionMode.WithTransaction Then
Return Connection.BeginTransaction()
Else
Return Connection.BeginTransaction()
End If
End Function
Private Function MaybeCommitTransaction(Transaction As FbTransaction)
If IsNothing(Transaction) Then
Return True
Else
Try
Transaction.Commit()
Return True
Catch ex As Exception
_logger.Error(ex)
Return False
End Try
End If
End Function
''' <summary>
''' Executes a non-query command.
''' </summary>
''' <param name="SqlCommand">The command to execute</param>
''' <param name="Connection">The Firebird connection to use</param>
''' <returns>True, if command was executed sucessfully. Otherwise false.</returns>
Public Function ExecuteNonQueryWithConnection(SqlCommand As String, Connection As FbConnection) As Boolean
_logger.Debug("Executing Non-Query: {0}", SqlCommand)
If Connection Is Nothing Then
Return Nothing
End If
Dim oTransaction As FbTransaction = Connection.BeginTransaction()
Try
Dim oCommand As New FbCommand With {
.CommandText = SqlCommand,
.Connection = Connection,
.Transaction = oTransaction
}
oCommand.ExecuteNonQuery()
Catch ex As Exception
_logger.Error(ex, $"Error in ExecuteNonQuery while executing command: '{SqlCommand}'")
Throw ex
Finally
oTransaction.Commit()
End Try
Return True
End Function
''' <summary>
''' Executes a non-query command.
''' </summary>
''' <param name="SqlCommand">The command to execute</param>
''' <returns>True, if command was executed sucessfully. Otherwise false.</returns>
Public Function ExecuteNonQuery(SqlCommand As String) As Boolean
Dim oConnection As FbConnection = GetConnection()
Dim oScalarValue As Object = ExecuteNonQueryWithConnection(SqlCommand, oConnection)
oConnection.Close()
Return oScalarValue
End Function
''' <summary>
''' Executes a sql query resulting in a scalar value.
''' </summary>
''' <param name="SqlQuery">The query to execute</param>
''' <param name="Connection">The Firebird connection to use</param>
''' <returns>The scalar value if the command was executed successfully. Nothing otherwise.</returns>
Public Function GetScalarValueWithConnection(SqlQuery As String, Connection As FbConnection) As Object
_logger.Debug("Fetching Scalar-Value: {0}", SqlQuery)
If Connection Is Nothing Then
Return Nothing
End If
Dim oTransaction As FbTransaction = Connection.BeginTransaction()
Dim oResult As Object
Try
Dim oCommand As New FbCommand With {
.CommandText = SqlQuery,
.Connection = Connection,
.Transaction = oTransaction
}
oResult = oCommand.ExecuteScalar()
Catch ex As Exception
_logger.Error(ex, $"Error in ReturnScalar while executing command: '{SqlQuery}'")
Throw ex
Finally
oTransaction.Commit()
End Try
Return oResult
End Function
''' <summary>
''' Executes a sql query resulting in a scalar value.
''' </summary>
''' <param name="SqlQuery">The query to execute</param>
''' <returns>The scalar value if the command was executed successfully. Nothing otherwise.</returns>
Public Function GetScalarValue(SqlQuery As String) As Object
Dim oConnection As FbConnection = GetConnection()
Dim oScalarValue As Object = GetScalarValueWithConnection(SqlQuery, oConnection)
oConnection.Close()
Return oScalarValue
End Function
''' <summary>
''' Executes a sql query resulting in a table of values.
''' </summary>
''' <param name="SqlQuery">The query to execute</param>
''' <param name="Connection">The Firebird connection to use</param>
''' <returns>A datatable containing the results if the command was executed successfully. Nothing otherwise.</returns>
Public Function GetDatatableWithConnection(SqlQuery As String, Connection As FbConnection, Optional TransactionMode As TransactionMode = TransactionMode.NoTransaction) As DataTable
_logger.Debug("Fetching Datatable: {0}", SqlQuery)
If Connection Is Nothing Then
Return Nothing
End If
Dim oTransaction = MaybeGetTransaction(Connection, TransactionMode)
Dim oDatatable As New DataTable() With {
.TableName = "DDRESULT"
}
Try
Dim oAdapter As New FbDataAdapter(New FbCommand With {
.CommandText = SqlQuery,
.Connection = Connection,
.Transaction = oTransaction
})
oAdapter.Fill(oDatatable)
Catch ex As Exception
_logger.Error(ex, $"Error in GetDatatableWithConnection while executing command: '{SqlQuery}'")
Throw ex
Finally
MaybeCommitTransaction(oTransaction)
End Try
Return oDatatable
End Function
''' <summary>
''' Executes a sql query resulting in a table of values.
''' </summary>
''' <param name="SqlQuery">The query to execute</param>
''' <returns>A datatable containing the results if the command was executed successfully. Nothing otherwise.</returns>
Public Function GetDatatable(SqlQuery As String, Optional TransactionMode As TransactionMode = TransactionMode.NoTransaction) As DataTable
Dim oConnection As FbConnection = GetConnection()
Dim oDatatable As DataTable = GetDatatableWithConnection(SqlQuery, oConnection, TransactionMode)
oConnection.Close()
Return oDatatable
End Function
End Class