Option Explicit On Imports System.Threading Imports DigitalData.Modules.Database Imports DigitalData.Modules.Language Imports DigitalData.Modules.Logging Imports Quartz Imports Quartz.Listener Public Class JobListener Inherits JobListenerSupport Public Overrides ReadOnly Property Name As String = "JobListener" Public Property Dataset As DataSet Private ReadOnly _Logger As Logger Private ReadOnly _LogConfig As LogConfig Private ReadOnly _MSSQL As MSSQLServer Public Sub New(LogConfig As LogConfig, MSSQL As MSSQLServer, ResultDataSet As DataSet) MyBase.New() _LogConfig = LogConfig _Logger = LogConfig.GetLogger() _MSSQL = MSSQL Dataset = ResultDataSet End Sub Public Overrides Function JobWasExecuted(context As IJobExecutionContext, jobException As JobExecutionException, Optional cancellationToken As CancellationToken = Nothing) As Task _Logger.Info("Job [{0}] was executed successfully. Saving Data.", context.JobDetail.Key) Dim oResult As JobResult = context.Result For Each oTableResult As JobResult.ResultTable In oResult.Tables Try _Logger.Debug("Saving Datatable [{0}]", oTableResult.Table) SaveDataTables(oTableResult) Catch ex As Exception _Logger.Error("Error while executing SaveDataTables for {0}", oTableResult.Table.TableName) End Try Next Return MyBase.JobWasExecuted(context, jobException, cancellationToken) End Function Public Sub ReplaceExistingTable(Name As String, Table As DataTable, DataSet As DataSet, Optional ChildTable As DataTable = Nothing) Try Dim oDatatableNameTemp As String = Name & "-TEMP" _Logger.Debug("DataTable [{0}] exists, renaming and replacing in DataSet", Name) ' Rename the new table, add TEMP suffix _Logger.Debug("Renaming new table [{0}] to [{1}]", Name, oDatatableNameTemp) Table.TableName = oDatatableNameTemp ' If child table exists, remove all connections to it If ChildTable IsNot Nothing Then _Logger.Debug("Removing relations/constraints on [{0}] and [{1}]", ChildTable.TableName, Name) ' Remove relations/constraints on child table Dim oChildTable As DataTable = DataSet.Tables.Item(ChildTable.TableName) If oChildTable IsNot Nothing Then oChildTable.Constraints.Clear() oChildTable.ChildRelations.Clear() End If ' Remove relations/constraints on parent table Dim oParentTable As DataTable = DataSet.Tables.Item(Name) If oParentTable IsNot Nothing Then oParentTable.Constraints.Clear() oParentTable.ChildRelations.Clear() End If End If ' Remove the temp table if it exists If DataSet.Tables.Contains(oDatatableNameTemp) Then _Logger.Debug("Removing Temp-Table [{0}]", oDatatableNameTemp) DataSet.Tables.Item(oDatatableNameTemp).ChildRelations.Clear() DataSet.Tables.Item(oDatatableNameTemp).Constraints.Clear() DataSet.Tables.Remove(oDatatableNameTemp) Else _Logger.Debug("Table [{0}] does not exist, skipping removal.", oDatatableNameTemp) End If ' Remove the current Table If DataSet.Tables.Contains(Name) Then _Logger.Debug("Removing Table [{0}]", Name) DataSet.Tables.Item(Name).Constraints.Clear() DataSet.Tables.Remove(Name) Else _Logger.Debug("Table [{0}] does not exist, skipping removal.", Name) End If ' Add the new table to the dataset _Logger.Debug("Adding Table [{0}] to Dataset", Table.TableName) DataSet.Tables.Add(Table) ' Rename the new table _Logger.Debug("Renaming new table [{0}] to [{1}]", oDatatableNameTemp, Name) DataSet.Tables.Item(oDatatableNameTemp).TableName = Name Catch ex As Exception _Logger.Error(ex) Throw ex End Try End Sub Public Sub AddNewTable(Name As String, Table As DataTable, DataSet As DataSet) _Logger.Debug("DataTable [{0}] does not exist, adding to DataSet", Name) DataSet.Tables.Add(Table) End Sub Public Function GetRelationName(ParentTableName As String, ChildTableName As String) As String Return $"{ParentTableName}-{ChildTableName}" End Function Public Sub AddRelation(ParentTableName As String, ParentColumnName As String, ChildTableName As String, ChildColumnName As String) Dim oChild As DataTable = Dataset.Tables.Item(ChildTableName) Dim oParent As DataTable = Dataset.Tables.Item(ParentTableName) Dim oRelationName As String = GetRelationName(ParentTableName, ChildTableName) Dim oParentColumn As DataColumn = oParent.Columns.Item(ParentColumnName) Dim oChildColumn As DataColumn = oChild.Columns.Item(ChildColumnName) _Logger.Debug("New Relation: {0}/{1} => {2}/{3}", ParentTableName, ParentColumnName, ChildTableName, ChildColumnName) Try _Logger.Debug("Creating Relation [{0}]", oRelationName) _Logger.Debug("ParentColumn exists: {0}", IsNothing(oParentColumn)) _Logger.Debug("ChildColumn exists: {0}", IsNothing(oChildColumn)) Dim oRelation As New DataRelation(oRelationName, oParentColumn, oChildColumn) _Logger.Debug("Adding Relation [{0}]", oRelationName) Dataset.Relations.Add(oRelation) Catch ex As ArgumentNullException _Logger.Error(ex) _Logger.Warn("ArgumentNullException in AddRelation: {0}", ex.Message) Catch ex As DuplicateNameException _Logger.Error(ex) _Logger.Warn("DuplicateNameException in AddRelation: {0}", ex.Message) Catch ex As InvalidConstraintException _Logger.Error(ex) _Logger.Warn("DuplicateNameException in AddRelation: {0}", ex.Message) Catch ex As ArgumentException _Logger.Error(ex) _Logger.Warn("ArgumentException in AddRelation: {0}", ex.Message) Catch ex As Exception _Logger.Error(ex) _Logger.Warn("Exception in AddRelation: {0}", ex.Message) End Try End Sub Public Sub SaveDataTables(Result As JobResult.ResultTable) Try Dim oTable As DataTable = Result.Table Dim oName As String = Result.DetailRow.Item("DT_NAME") Dim oDetailId As Integer = Result.DetailRow.Item("GUID") ' Used for debugging relations and constraints '_Logger.Debug("Dataset BEFORE saving datatables") 'ListTables(Dataset) If Dataset.Tables.Contains(oName) Then _Logger.Debug("Datatable [{0}] already exists, replacing.", oName) ' Replace existing table If Result.ChildTable IsNot Nothing Then ReplaceExistingTable(oName, oTable, Dataset, Result.ChildTable) AddRelation(oName, Result.TableRelationColumn, Result.ChildTable.TableName, Result.ChildRelationColumn) Else ReplaceExistingTable(oName, oTable, Dataset) End If Else _Logger.Debug("Datatable [{0}] does not exist yet, adding.", oName) AddNewTable(oName, oTable, Dataset) If Result.ChildTable IsNot Nothing Then AddNewTable(Result.ChildTable.TableName, Result.ChildTable, Dataset) AddRelation(oName, Result.TableRelationColumn, Result.ChildTable.TableName, Result.ChildRelationColumn) End If End If ' Used for debugging relations and constraints '_Logger.Debug("Dataset AFTER saving datatables") 'ListTables(Dataset) Dim oMemoryUsage = GC.GetTotalMemory(True) Dim oUsageString = Utils.BytesToString(oMemoryUsage) _Logger.Debug("Estimated memory usage after Job is [{0}]", oUsageString) _MSSQL.ExecuteNonQuery($"INSERT INTO TBAPPSERV_CRON_DETAIL_HISTORY (DETAIL_ID) VALUES ({oDetailId})") Catch ex As Exception _Logger.Warn("Unexpected error in JobListener: {0}", ex.Message) _Logger.Error(ex) End Try End Sub Private Sub ListTables(dataset As DataSet) Dim oIndex As Integer = 1 For Each oTable As DataTable In dataset.Tables _Logger.Debug("Table: [{0}] ({1})", oTable.TableName, oIndex) _Logger.Debug("-> Listing Constraints for [{0}]:", oTable.TableName) For Each oConstraint As Constraint In oTable.Constraints _Logger.Debug("---> Constraint: [{0}]", oConstraint.ConstraintName) Next _Logger.Debug("-> Listing Child-Relations for [{0}]:", oTable.TableName) For Each oRelation As DataRelation In oTable.ChildRelations _Logger.Debug("---> Relation: [{0}] ", oRelation.RelationName) Next oIndex += 1 Next End Sub End Class