474 lines
20 KiB
VB.net
474 lines
20 KiB
VB.net
Imports DigitalData.Modules.Database
|
|
Imports DigitalData.Modules.EDMI.API
|
|
Imports DigitalData.Modules.EDMI.API.Constants
|
|
Imports DigitalData.Modules.EDMI.API.EDMIServiceReference
|
|
Imports DigitalData.Modules.Logging
|
|
Imports DigitalData.Modules.Language.Utils
|
|
|
|
Public Class DatabaseWithFallback
|
|
Private ReadOnly _Logger As Logger
|
|
Private ReadOnly _Client As Client
|
|
Private ReadOnly _ClientConfig As GlobalStateClientConfiguration
|
|
Private ReadOnly _DatabaseECM As MSSQLServer
|
|
Private _DatabaseIDB As MSSQLServer
|
|
|
|
''' <summary>
|
|
''' Options for GetDatatable
|
|
''' </summary>
|
|
Public Class GetDatatableOptions
|
|
Public ReadOnly FallbackSQL
|
|
Public ReadOnly FallbackType
|
|
|
|
''' <summary>
|
|
''' Filter expression for the cached Datatable
|
|
''' </summary>
|
|
Public Property FilterExpression As String = ""
|
|
''' <summary>
|
|
''' Columns to sort the cached Datatable by
|
|
''' </summary>
|
|
Public Property SortByColumn As String = ""
|
|
''' <summary>
|
|
''' Force the fallback, skipping the service completely
|
|
''' </summary>
|
|
Public Property ForceFallback As Boolean = False
|
|
''' <summary>
|
|
''' Connection Id to use, references TBDD_CONNECTION
|
|
''' </summary>
|
|
Public Property ConnectionId As Integer = 0
|
|
|
|
''' <summary>
|
|
''' Creates a new options object for GetDatatable options
|
|
''' </summary>
|
|
''' <param name="pFallbackSQL">SQL Command to execute as fallback</param>
|
|
''' <param name="pFallbackType">Named Database to use for the fallback SQL Command</param>
|
|
Public Sub New(pFallbackSQL As String, pFallbackType As Constants.DatabaseType)
|
|
FallbackSQL = pFallbackSQL
|
|
FallbackType = pFallbackType
|
|
End Sub
|
|
End Class
|
|
|
|
Public Sub New(LogConfig As LogConfig, Client As Client, DatabaseECM As MSSQLServer, DatabaseIDB As MSSQLServer)
|
|
_Logger = LogConfig.GetLogger()
|
|
_Client = Client
|
|
_DatabaseECM = DatabaseECM
|
|
_DatabaseIDB = DatabaseIDB
|
|
|
|
_Logger.Debug("Client exists: [{0}]", Not IsNothing(Client))
|
|
_Logger.Debug("DatabaseECM exists: [{0}]", Not IsNothing(DatabaseECM))
|
|
_Logger.Debug("DatabaseIDB exists: [{0}]", Not IsNothing(DatabaseIDB))
|
|
|
|
' Load client config, will throw if client is not yet connected to service
|
|
_ClientConfig = Client?.ClientConfig
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Set the IDB Database class after initializing the class.
|
|
''' It is now your responsibility to make sure to not use any IDB calls before calling this method.
|
|
''' </summary>
|
|
Public Sub InitializeIDB(pDatabaseIDB As MSSQLServer)
|
|
_DatabaseIDB = pDatabaseIDB
|
|
End Sub
|
|
|
|
Public Function GetConnectionString(pConnectionId As Integer) As String
|
|
Return _DatabaseECM.GetConnectionStringForId(pConnectionId)
|
|
End Function
|
|
|
|
#Region "GetDatatable"
|
|
Public Function GetDatatableECM(pSQL As String) As DataTable
|
|
Return GetDatatable(New GetDatatableOptions(pSQL, Constants.DatabaseType.ECM))
|
|
End Function
|
|
|
|
Public Async Function GetDatatableECMAsync(pSQL As String) As Task(Of DataTable)
|
|
Return Await Task.Run(Function() GetDatatableECM(pSQL))
|
|
End Function
|
|
|
|
Public Function GetDatatableIDB(pSQL As String) As DataTable
|
|
Return GetDatatable(New GetDatatableOptions(pSQL, Constants.DatabaseType.IDB))
|
|
End Function
|
|
|
|
Public Async Function GetDatatableIDBAsync(pSQL As String) As Task(Of DataTable)
|
|
Return Await Task.Run(Function() GetDatatableIDB(pSQL))
|
|
End Function
|
|
|
|
Public Function GetDatatableWithConnection(pSQL As String, pConnectionId As Integer) As DataTable
|
|
Return GetDatatable(New GetDatatableOptions(pSQL, Constants.DatabaseType.None) With {.ConnectionId = pConnectionId})
|
|
End Function
|
|
|
|
Public Async Function GetDatatableWithConnectionAsync(pSQL As String, pConnectionId As Integer) As Task(Of DataTable)
|
|
Return Await Task.Run(Function() GetDatatableWithConnection(pSQL, pConnectionId))
|
|
End Function
|
|
#End Region
|
|
|
|
#Region "GetScalarValue"
|
|
Public Function GetScalarValueECM(pSQL As String) As Object
|
|
Return GetScalarValue(pSQL, Constants.DatabaseType.ECM)
|
|
End Function
|
|
|
|
Public Async Function GetScalarValueECMAsync(pSQL As String) As Task(Of Object)
|
|
Return Await Task.Run(Function() GetScalarValueECM(pSQL))
|
|
End Function
|
|
|
|
Public Function GetScalarValueIDB(pSQL As String) As Object
|
|
Return GetScalarValue(pSQL, Constants.DatabaseType.IDB)
|
|
End Function
|
|
|
|
Public Async Function GetScalarValueIDBAsync(pSQL As String) As Task(Of Object)
|
|
Return Await Task.Run(Function() GetScalarValueIDB(pSQL))
|
|
End Function
|
|
|
|
Public Function GetScalarValueWithConnection(pSQL As String, pConnectionId As Integer) As Object
|
|
Return GetScalarValue(pSQL, Constants.DatabaseType.None, pConnectionId:=pConnectionId)
|
|
End Function
|
|
|
|
Public Async Function GetScalarValueWithConnectionAsync(pSQL As String, pConnectionId As Integer) As Task(Of Object)
|
|
Return Await Task.Run(Function() GetScalarValueWithConnection(pSQL, pConnectionId))
|
|
End Function
|
|
#End Region
|
|
|
|
#Region "ExecuteNonQuery"
|
|
Public Function ExecuteNonQueryECM(pSQL As String) As Boolean
|
|
Return ExecuteNonQuery(pSQL, Constants.DatabaseType.ECM)
|
|
End Function
|
|
|
|
Public Async Function ExecuteNonQueryECMAsync(pSQL As String) As Task(Of Boolean)
|
|
Return Await Task.Run(Function() ExecuteNonQueryECM(pSQL))
|
|
End Function
|
|
|
|
Public Function ExecuteNonQueryIDB(pSQL As String) As Boolean
|
|
Return ExecuteNonQuery(pSQL, Constants.DatabaseType.IDB)
|
|
End Function
|
|
|
|
Public Async Function ExecuteNonQueryIDBAsync(pSQL As String) As Task(Of Boolean)
|
|
Return Await Task.Run(Function() ExecuteNonQueryIDB(pSQL))
|
|
End Function
|
|
|
|
Public Function ExecuteNonQueryWithConnection(pSQL As String, pConnectionId As Integer) As Boolean
|
|
Return ExecuteNonQuery(pSQL, Constants.DatabaseType.None, pConnectionId:=pConnectionId)
|
|
End Function
|
|
|
|
Public Async Function ExecuteNonQueryWithConnectionAsync(pSQL As String, pConnectionId As Integer) As Task(Of Boolean)
|
|
Return Await Task.Run(Function() ExecuteNonQueryWithConnection(pSQL, pConnectionId))
|
|
End Function
|
|
#End Region
|
|
|
|
|
|
''' <summary>
|
|
''' Returns a Datatable by trying to fetch a cached version from the service, then querying the database through the service and querying the database directly as fallback.
|
|
''' </summary>
|
|
''' <param name="pDataTableName">Name of the Cached Datatable</param>
|
|
''' <param name="pOptions">Options object</param>
|
|
Public Function GetDatatable(pDataTableName As String, pOptions As GetDatatableOptions) As DataTable
|
|
Return GetDatatable(pDataTableName, pOptions.FallbackSQL, pOptions.FallbackType, pOptions.FilterExpression, pOptions.SortByColumn, pOptions.ForceFallback, pOptions.ConnectionId)
|
|
End Function
|
|
|
|
Public Function GetDatatable(pSQL As String, pConnectionId As Integer) As DataTable
|
|
Return GetDatatable("FORCE_FALLBACK", pSQL, Constants.DatabaseType.ECM, pSortByColumn:=Nothing, pForceFallback:=False, pConnectionId:=pConnectionId)
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Returns a datatable directly from the database.
|
|
''' </summary>
|
|
''' <param name="pOptions">Options object</param>
|
|
Public Function GetDatatable(pOptions As GetDatatableOptions) As DataTable
|
|
Dim oForceFallback = True
|
|
Return GetDatatable("FORCE_FALLBACK", pOptions.FallbackSQL, pOptions.FallbackType, pOptions.FilterExpression, pOptions.SortByColumn, oForceFallback, pOptions.ConnectionId)
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Returns a Datatable by trying to fetch a cached version from the service, then querying the database through the service and querying the database directly as fallback.
|
|
''' </summary>
|
|
''' <param name="pDataTableName">Name of the Cached Datatable</param>
|
|
''' <param name="pFallbackSQL">SQL Command to execute as fallback</param>
|
|
''' <param name="pFallbackType">Named Database to use for the fallback SQL Command</param>
|
|
''' <param name="pFilterExpression">Filter expression for the cached Datatable</param>
|
|
''' <param name="pSortByColumn">Columns to sort the cached Datatable by</param>
|
|
''' <param name="pForceFallback">Force the fallback, skipping the service completely</param>
|
|
''' <param name="pConnectionId">Connection Id to use, references TBDD_CONNECTION</param>
|
|
Public Function GetDatatable(pDataTableName As String, pFallbackSQL As String, pFallbackType As Constants.DatabaseType, Optional pFilterExpression As String = "", Optional pSortByColumn As String = "", Optional pForceFallback As Boolean = False, Optional pConnectionId As Integer = 0) As DataTable
|
|
Try
|
|
Dim oResult As DataTable = Nothing
|
|
Dim oTableResult As TableResult = Nothing
|
|
|
|
' If there is no client, we assume there is no service (configured)
|
|
If _Client Is Nothing Then
|
|
Return GetDatatableFromDatabase(pFallbackSQL, pFallbackType, pConnectionId)
|
|
End If
|
|
|
|
' If ForceFallback flag is set, we go to database immediately
|
|
If pForceFallback Or _ClientConfig.ForceDirectDatabaseAccess Then
|
|
Return GetDatatableFromDatabase(pFallbackSQL, pFallbackType, pConnectionId)
|
|
End If
|
|
|
|
' If the table is not cached, we try going through the service
|
|
If Not IsTableCached(pDataTableName) Then
|
|
Return GetDatatableFromService(pFallbackSQL, pFallbackType, pConnectionId)
|
|
End If
|
|
|
|
' If there is a proper ConnectionId, we try going through the service
|
|
If pConnectionId > 0 Then
|
|
Return GetDatatableFromService(pFallbackSQL, pFallbackType, pConnectionId)
|
|
End If
|
|
|
|
Try
|
|
oTableResult = _Client.GetDatatableByName(pDataTableName, pFilterExpression, pSortByColumn)
|
|
Catch ex As Exception
|
|
_Logger.Error(ex)
|
|
oTableResult = Nothing
|
|
End Try
|
|
|
|
If oTableResult Is Nothing OrElse oTableResult.OK = False Then
|
|
_Logger.Warn("Datatable [{0}] could not be fetched from AppServer Cache. Falling back to direct Database Access.", pDataTableName)
|
|
Return GetDatatableFromDatabase(pFallbackSQL, pFallbackType, pConnectionId)
|
|
Else
|
|
Return oTableResult.Table
|
|
End If
|
|
|
|
Catch ex As Exception
|
|
_Logger.Error(ex)
|
|
Return Nothing
|
|
|
|
End Try
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Returns a Scalar Value by querying the database through the service and querying the database directly as fallback.
|
|
''' </summary>
|
|
''' <param name="pSQL">SQL Command to execute as fallback</param>
|
|
''' <param name="pDatabaseType">Named Database to use for the fallback SQL Command</param>
|
|
''' <param name="pForceFallback">Force the fallback, skipping the service completely</param>
|
|
''' <param name="pConnectionId">Connection Id to use, references TBDD_CONNECTION</param>
|
|
Public Function GetScalarValue(pSQL As String, pDatabaseType As Constants.DatabaseType, Optional pForceFallback As Boolean = False, Optional pConnectionId As Integer = 0) As Object
|
|
Try
|
|
' If there is no client, we assume there is no service (configured)
|
|
If _Client Is Nothing Then
|
|
Return GetScalarValueFromDatabase(pSQL, pDatabaseType, pConnectionId)
|
|
End If
|
|
|
|
' If ForceFallback flag is set, we go to database immediately
|
|
If pForceFallback Or _ClientConfig.ForceDirectDatabaseAccess Then
|
|
Return GetScalarValueFromDatabase(pSQL, pDatabaseType, pConnectionId)
|
|
End If
|
|
|
|
Return GetScalarValueFromService(pSQL, pDatabaseType, pConnectionId)
|
|
|
|
Catch ex As Exception
|
|
_Logger.Error(ex)
|
|
Return Nothing
|
|
|
|
End Try
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Returns a Scalar Value by querying the database through the service and querying the database directly as fallback.
|
|
''' </summary>
|
|
''' <param name="pSQL">SQL Command to execute as fallback</param>
|
|
''' <param name="pDatabaseType">Named Database to use for the fallback SQL Command</param>
|
|
''' <param name="pForceFallback">Force the fallback, skipping the service completely</param>
|
|
''' <param name="pConnectionId">Connection Id to use, references TBDD_CONNECTION</param>
|
|
Public Function ExecuteNonQuery(pSQL As String, pDatabaseType As Constants.DatabaseType, Optional pForceFallback As Boolean = False, Optional pConnectionId As Integer = 0) As Boolean
|
|
Try
|
|
Dim oResult As DataTable = Nothing
|
|
Dim oTableResult As TableResult = Nothing
|
|
|
|
' If there is no client, we assume there is no service (configured)
|
|
If _Client Is Nothing Then
|
|
Return ExecuteNonQueryFromDatabase(pSQL, pDatabaseType, pConnectionId)
|
|
End If
|
|
|
|
' If ForceFallback flag is set, we go to database immediately
|
|
If pForceFallback Or _ClientConfig.ForceDirectDatabaseAccess Then
|
|
Return ExecuteNonQueryFromDatabase(pSQL, pDatabaseType, pConnectionId)
|
|
End If
|
|
|
|
Return ExecuteNonQueryFromService(pSQL, pDatabaseType, pConnectionId)
|
|
|
|
Catch ex As Exception
|
|
_Logger.Error(ex)
|
|
Return Nothing
|
|
|
|
End Try
|
|
End Function
|
|
|
|
Private Function IsTableCached(pName As String) As Boolean
|
|
If _Client Is Nothing Then
|
|
Return False
|
|
End If
|
|
|
|
Return _Client.CachedTables.Contains(pName.ToUpper)
|
|
End Function
|
|
|
|
Private Function GetDatatableFromService(pSQLCommand As String, DatabaseType As Constants.DatabaseType, pConnectionId As Integer) As DataTable
|
|
Try
|
|
Dim oResult As GetDatatableResponse = Nothing
|
|
|
|
Select Case DatabaseType
|
|
Case Constants.DatabaseType.ECM
|
|
oResult = _Client.GetDatatableFromECM(pSQLCommand)
|
|
|
|
Case Constants.DatabaseType.IDB
|
|
oResult = _Client.GetDatatableFromIDB(pSQLCommand)
|
|
|
|
Case Else
|
|
Return GetDatatableFromDatabase(pSQLCommand, DatabaseType, pConnectionId)
|
|
|
|
End Select
|
|
|
|
If oResult Is Nothing Then
|
|
Throw New ApplicationException("Unexpected server error ocurred!")
|
|
End If
|
|
|
|
If oResult.OK = False Then
|
|
Throw New ApplicationException(oResult.ErrorMessage)
|
|
End If
|
|
|
|
Return oResult.Table
|
|
|
|
Catch ex As Exception
|
|
_Logger.Warn("GetDatatableFromService failed. Falling back to direct database access.")
|
|
_Logger.Error(ex)
|
|
Return GetDatatableFromDatabase(pSQLCommand, DatabaseType, pConnectionId)
|
|
|
|
End Try
|
|
End Function
|
|
|
|
|
|
Private Function GetDatatableFromDatabase(pSQLCommand As String, DatabaseType As Constants.DatabaseType, pConnectionId As Integer) As DataTable
|
|
Try
|
|
Select Case DatabaseType
|
|
Case Constants.DatabaseType.IDB
|
|
Return _DatabaseIDB.GetDatatable(pSQLCommand)
|
|
|
|
Case Else
|
|
If pConnectionId > 0 Then
|
|
Dim oConnectionString = _DatabaseECM.Get_ConnectionStringforID(pConnectionId)
|
|
Return _DatabaseECM.GetDatatableWithConnection(pSQLCommand, oConnectionString)
|
|
Else
|
|
Return _DatabaseECM.GetDatatable(pSQLCommand)
|
|
End If
|
|
|
|
End Select
|
|
|
|
Catch ex As Exception
|
|
_Logger.Error(ex)
|
|
Return Nothing
|
|
|
|
End Try
|
|
End Function
|
|
|
|
Private Function GetScalarValueFromService(pSQLCommand As String, DatabaseType As Constants.DatabaseType, pConnectionId As Integer) As Object
|
|
Try
|
|
Dim oResult As GetScalarValueResponse = Nothing
|
|
|
|
Select Case DatabaseType
|
|
Case Constants.DatabaseType.ECM
|
|
oResult = _Client.GetScalarValueFromECM(pSQLCommand)
|
|
|
|
Case Constants.DatabaseType.IDB
|
|
oResult = _Client.GetScalarValueFromIDB(pSQLCommand)
|
|
|
|
Case Else
|
|
Return GetScalarValueFromDatabase(pSQLCommand, DatabaseType, pConnectionId)
|
|
|
|
End Select
|
|
|
|
If oResult Is Nothing Then
|
|
Throw New ApplicationException("Unexpected server error ocurred!")
|
|
End If
|
|
|
|
If oResult.OK = False Then
|
|
Throw New ApplicationException(oResult.ErrorMessage)
|
|
End If
|
|
|
|
Return oResult.Scalar
|
|
|
|
Catch ex As Exception
|
|
_Logger.Warn("GetScalarValueFromService failed. Falling back to direct database access.")
|
|
_Logger.Error(ex)
|
|
Return GetScalarValueFromDatabase(pSQLCommand, DatabaseType, pConnectionId)
|
|
|
|
End Try
|
|
End Function
|
|
|
|
|
|
Private Function GetScalarValueFromDatabase(pSQLCommand As String, DatabaseType As Constants.DatabaseType, pConnectionId As Integer) As Object
|
|
Try
|
|
Select Case DatabaseType
|
|
Case Constants.DatabaseType.IDB
|
|
Return _DatabaseIDB.GetScalarValue(pSQLCommand)
|
|
|
|
Case Else
|
|
If pConnectionId > 0 Then
|
|
Dim oConnectionString = _DatabaseECM.Get_ConnectionStringforID(pConnectionId)
|
|
Return _DatabaseECM.GetScalarValueWithConnection(pSQLCommand, oConnectionString)
|
|
Else
|
|
Return _DatabaseECM.GetScalarValue(pSQLCommand)
|
|
End If
|
|
|
|
End Select
|
|
|
|
Catch ex As Exception
|
|
_Logger.Error(ex)
|
|
Return Nothing
|
|
|
|
End Try
|
|
End Function
|
|
|
|
Private Function ExecuteNonQueryFromService(pSQLCommand As String, DatabaseType As Constants.DatabaseType, pConnectionId As Integer) As Boolean
|
|
Try
|
|
Dim oResult As ExecuteNonQueryResponse = Nothing
|
|
|
|
Select Case DatabaseType
|
|
Case Constants.DatabaseType.ECM
|
|
oResult = _Client.ExecuteNonQueryFromECM(pSQLCommand)
|
|
|
|
Case Constants.DatabaseType.IDB
|
|
oResult = _Client.ExecuteNonQueryFromIDB(pSQLCommand)
|
|
|
|
Case Else
|
|
Return ExecuteNonQueryFromDatabase(pSQLCommand, DatabaseType, pConnectionId)
|
|
|
|
End Select
|
|
|
|
If oResult Is Nothing Then
|
|
Throw New ApplicationException("Unexpected server error ocurred!")
|
|
End If
|
|
|
|
If oResult.OK = False Then
|
|
Throw New ApplicationException(oResult.ErrorMessage)
|
|
End If
|
|
|
|
Return oResult.Result
|
|
|
|
Catch ex As Exception
|
|
_Logger.Warn("ExecuteNonQueryFromService failed. Falling back to direct database access.")
|
|
_Logger.Error(ex)
|
|
Return ExecuteNonQueryFromDatabase(pSQLCommand, DatabaseType, pConnectionId)
|
|
|
|
End Try
|
|
End Function
|
|
|
|
Private Function ExecuteNonQueryFromDatabase(pSQLCommand As String, DatabaseType As Constants.DatabaseType, pConnectionId As Integer) As Boolean
|
|
Try
|
|
Select Case DatabaseType
|
|
Case Constants.DatabaseType.IDB
|
|
Return _DatabaseIDB.ExecuteNonQuery(pSQLCommand)
|
|
|
|
Case Else
|
|
If pConnectionId > 0 Then
|
|
Dim oConnectionString = _DatabaseECM.Get_ConnectionStringforID(pConnectionId)
|
|
Return _DatabaseECM.ExecuteNonQueryWithConnection(pSQLCommand, oConnectionString)
|
|
Else
|
|
Return _DatabaseECM.ExecuteNonQuery(pSQLCommand)
|
|
End If
|
|
|
|
End Select
|
|
|
|
Catch ex As Exception
|
|
_Logger.Error(ex)
|
|
Return False
|
|
|
|
End Try
|
|
End Function
|
|
End Class
|
|
|