Verbesserung der Datenvalidierung und Fehlerbehandlung

In `ClassCockpit.vb` wurden mehrere Sicherheitsprüfungen und
Normalisierungen in der Methode `CreateCockpit` hinzugefügt,
einschließlich der Überprüfung auf leere Tabellen, fehlende
Spalten und ungültige Primärschlüssel. Duplikate und ungültige
`PARENT_ID`-Referenzen werden nun entfernt oder korrigiert.

In `frmMonitor.vb` wurde die Fehlerbehandlung beim Laden von
Dokumenten verbessert, einschließlich Validierung des Dateipfads
und lokalisierter Fehlermeldungen.

Ein neues Feld `CFG_SEQUENCE` wurde in `frmCockpitConfig.vb`
hinzugefügt, und ein Aufruf zu `AppendCountsToTreeAsync()` wurde
in `frmMain.vb` integriert.

Neue Ressourcen- und Projektdateien (`ClassCockpit.vb`,
`frmMain.aa.resx`) wurden in `taskFLOW.vbproj` hinzugefügt.
This commit is contained in:
Developer01
2026-09-04 09:28:11 +02:00
parent c638ab71a0
commit 4ba29ce57b
5 changed files with 148 additions and 42 deletions

View File

@@ -4,6 +4,34 @@
Try
LOGGER.Debug("=== TreeView Data Analysis ===")
LOGGER.Debug($"Total rows: {pDTNodes.Rows.Count}")
' ===== SAFETY CHECKS / NORMALISIERUNGEN =====
If pDTNodes Is Nothing OrElse pDTNodes.Rows.Count = 0 Then
LOGGER.Warn("CreateCockpit: pDTNodes is Nothing or empty - nothing to bind")
Exit Sub
End If
' Prüfen ob Primärschlüssel-Spalte existiert
If Not pDTNodes.Columns.Contains("PK_CFG_COCKPIT_DEFINITION_ID") Then
LOGGER.Error("CreateCockpit: Required column 'PK_CFG_COCKPIT_DEFINITION_ID' is missing - aborting cockpit creation")
Exit Sub
End If
' Entferne Zeilen mit NULL/ungültigem PK (können beim Binding zu Duplikat-Keys führen)
Dim rowsWithNullPk As New List(Of DataRow)
For Each r As DataRow In pDTNodes.Rows
If IsDBNull(r("PK_CFG_COCKPIT_DEFINITION_ID")) Then
rowsWithNullPk.Add(r)
End If
Next
If rowsWithNullPk.Count > 0 Then
LOGGER.Warn($"CreateCockpit: Found {rowsWithNullPk.Count} row(s) with NULL PK - removing them to avoid TreeList key errors")
For Each r As DataRow In rowsWithNullPk
r.Delete()
Next
pDTNodes.AcceptChanges()
End If
' ===== NUR AKTIVE KNOTEN BEHALTEN =====
If pDTNodes.Columns.Contains("ACTIVE") And pAdmin = False Then
Dim oInactiveRows As DataRow() = pDTNodes.Select("ACTIVE = 0 OR ACTIVE IS NULL")
@@ -42,6 +70,54 @@
End If
End If
' ===== NULL-PARENT_IDS NORMALISIEREN (NULL -> 0) =====
If pDTNodes.Columns.Contains("PARENT_ID") Then
For Each r As DataRow In pDTNodes.Rows
If IsDBNull(r("PARENT_ID")) Then
r("PARENT_ID") = 0
End If
Next
Else
' Falls PARENT_ID fehlt, füge Spalte hinzu und setze 0
LOGGER.Warn("CreateCockpit: 'PARENT_ID' column missing - adding and setting to 0")
pDTNodes.Columns.Add("PARENT_ID", GetType(Integer))
For Each r As DataRow In pDTNodes.Rows
r("PARENT_ID") = 0
Next
End If
pDTNodes.AcceptChanges()
' ===== DUPLIKATE PKS ERMITTELN UND ENTFERNEN =====
Dim dupGroups = pDTNodes.AsEnumerable().
GroupBy(Function(r) Convert.ToInt32(r("PK_CFG_COCKPIT_DEFINITION_ID"))).
Where(Function(g) g.Count() > 1).ToList()
If dupGroups.Count > 0 Then
For Each g In dupGroups
LOGGER.Warn($"CreateCockpit: Duplicate PK detected: {g.Key}. Keeping first occurrence, removing {g.Count() - 1} duplicate row(s).")
Dim firstSeen As Boolean = False
For Each rr As DataRow In g
If Not firstSeen Then
firstSeen = True
Continue For
End If
rr.Delete()
Next
Next
pDTNodes.AcceptChanges()
End If
' ===== PARENT_IDs REFERENZEN PRÜFEN =====
Dim existingKeys As New HashSet(Of Integer)(pDTNodes.AsEnumerable().Select(Function(r) Convert.ToInt32(r("PK_CFG_COCKPIT_DEFINITION_ID"))))
For Each r As DataRow In pDTNodes.Rows
Dim pid As Integer = Convert.ToInt32(r("PARENT_ID"))
If pid <> 0 AndAlso Not existingKeys.Contains(pid) Then
LOGGER.Warn($"CreateCockpit: ParentId {pid} referenced by PK {r("PK_CFG_COCKPIT_DEFINITION_ID")} does not exist - setting ParentId to 0")
r("PARENT_ID") = 0
End If
Next
pDTNodes.AcceptChanges()
Dim rootCount = pDTNodes.AsEnumerable().Count(Function(r) Not IsDBNull(r("PARENT_ID")) AndAlso CInt(r("PARENT_ID")) = 0)
LOGGER.Debug($"Root nodes (PARENT_ID = 0): {rootCount}")
@@ -67,16 +143,6 @@
' ===== Jetzt DataSource zuweisen =====
myTreeView.DataSource = pDTNodes
'' ===== DEBUG: ImageList-Inhalt prüfen =====
'If myTreeView.SelectImageList IsNot Nothing Then
' LOGGER.Debug($"SelectImageList hat {myTreeView.SelectImageList.Images.Count} Bilder")
' For i As Integer = 0 To myTreeView.SelectImageList.Images.Count - 1
' LOGGER.Debug($" Image Index {i}: {myTreeView .SelectImageList.Images.Keys(i)}")
' Next
'Else
' LOGGER.Warn("SelectImageList ist Nothing!")
'End If
AddHandler myTreeView.CustomDrawNodeCell, AddressOf TreeList_Config_CustomDrawNodeCell
' ===== MODERNES DESIGN =====
@@ -134,24 +200,6 @@
LOGGER.Warn("Load_Treeview: No overview nodes (TYPE_ID=0) found - keeping default collapsed state")
End If
'' ===== DETAILLIERTES LOGGING =====
'LOGGER.Debug("=== DETAILED NODE STRUCTURE AFTER SETUP ===")
'LOGGER.Debug($"TreeList State - AllNodesCount: {TreeList_Cockpit.AllNodesCount}, RootNodes: {TreeList_Cockpit.Nodes.Count}")
'Dim allNodesList As New List(Of DevExpress.XtraTreeList.Nodes.TreeListNode)
'CollectAllNodes(TreeList_Cockpit.Nodes, allNodesList)
'LOGGER.Debug($"Total nodes collected recursively: {allNodesList.Count}")
'For Each node As DevExpress.XtraTreeList.Nodes.TreeListNode In allNodesList
' Dim nodeId = node.GetValue("PK_CFG_COCKPIT_DEFINITION_ID")
' Dim nodeName = node.GetValue("NAME")
' Dim nodeParent = node.GetValue("PARENT_ID")
' Dim level = node.Level
' Dim parentInfo = If(node.ParentNode Is Nothing, "NULL", $"ID={node.ParentNode.GetValue("PK_CFG_COCKPIT_DEFINITION_ID")}")
' LOGGER.Debug($" [Level {level}] ID={nodeId}, NAME={nodeName}, PARENT_ID={nodeParent}, ParentNode={parentInfo}, HasChildren={node.HasChildren}, ChildCount={node.Nodes.Count}, IsExpanded={node.Expanded}")
'Next
Catch ex As Exception
LOGGER.Error($"Error in CreateCockpit: {ex.Message}")
End Try
@@ -186,4 +234,4 @@
LOGGER.Error(ex)
End Try
End Sub
End Class
End Class

View File

@@ -895,7 +895,8 @@ Public Class frmCockpitConfig
' ===== SQL-FELDER IM TREEVIEW-KNOTEN AKTUALISIEREN =====
currentNode.SetValue("SQL_QUERY", _currentCockpitDefinition.SQL_Query)
currentNode.SetValue("SQL_QUERY_COUNT", _currentCockpitDefinition.SQL_Query_Count)
LOGGER.Debug($"TreeView SQL fields updated - SQL_Query length: {_currentCockpitDefinition.SQL_Query.Length}, SQL_Query_Count length: {_currentCockpitDefinition.SQL_Query_Count.Length}")
currentNode.SetValue("CFG_SEQUENCE", _currentCockpitDefinition.CFG_Sequence)
LOGGER.Debug($"TreeView SQL fields updated - SQL_Query length: {_currentCockpitDefinition.SQL_Query.Length}, SQL_Query_Count length: {_currentCockpitDefinition.SQL_Query_Count.Length}")
' TreeView visuell aktualisieren
TreeList_Cockpit.RefreshNode(currentNode)

View File

@@ -564,7 +564,7 @@ Public Class frmMain
End If
Dim clsck As New ClassCockpit()
clsck.CreateCockpit(oDT_STRUCTURE_NODES, TreeList_Cockpit, False)
AppendCountsToTreeAsync()
Catch ex As Exception
LOGGER.Error(ex)
Finally

View File

@@ -182,11 +182,25 @@ Public Class frmMonitor
'_frmDocView.LoadFile(oDocPath)
If File.Exists(oDocPath) Then
DocumentViewerMonitor.LoadFile_FromPath(oDocPath)
BarStaticItemInfo.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
DocumentViewerMonitor.Visible = True
' DocumentViewerMonitor.RightOnlyView(USER_RIGHT_VIEW_ONLY)
Try
If DocumentViewerMonitor Is Nothing Then
LOGGER.Error("DocumentViewerMonitor is Nothing in Load_Doc")
BarStaticItemInfo.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
BarStaticItemInfo.Caption = "DocView not initialized"
DocumentViewerMonitor.Visible = False
Else
DocumentViewerMonitor.LoadFile_FromPath(oDocPath)
BarStaticItemInfo.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
DocumentViewerMonitor.Visible = True
' DocumentViewerMonitor.RightOnlyView(USER_RIGHT_VIEW_ONLY)
End If
Catch ex As Exception
LOGGER.Error(ex)
BarStaticItemInfo.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
BarStaticItemInfo.Caption = "Error loading document"
DocumentViewerMonitor.Visible = False
MsgBox(ex.Message, MsgBoxStyle.Critical, "Error in LoadDoc:")
End Try
Else
BarStaticItemInfo.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
BarStaticItemInfo.Caption = $"File is not existing or accessible!"
@@ -459,16 +473,55 @@ Public Class frmMonitor
End If
BarButtonItem3.Down = True
Dim oDocPath
Dim oDocPath As String = String.Empty
Try
oDocPath = GridView1.GetFocusedRowCellValue(GridView1.Columns("FULL_FILE_PATH"))
oDocPath = Convert.ToString(GridView1.GetFocusedRowCellValue(GridView1.Columns("FULL_FILE_PATH")))
Catch ex As Exception
LOGGER.Warn($"Error getting DocPath in Monitor: {ex.Message}")
Exit Sub
oDocPath = String.Empty
End Try
' Validierungen einbauen, damit LoadFile_FromPath keine unhandled NullReferenceException wirft
If String.IsNullOrWhiteSpace(oDocPath) Then
LOGGER.Warn("BarButtonItem3: No document path available")
BarStaticItemInfo.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
If USER_LANGUAGE = "de-DE" Then
BarStaticItemInfo.Caption = "Kein Dateipfad verfügbar"
Else
BarStaticItemInfo.Caption = "No file path available"
End If
Exit Sub
End If
If Not File.Exists(oDocPath) Then
LOGGER.Warn($"BarButtonItem3: File does not exist: {oDocPath}")
BarStaticItemInfo.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
If USER_LANGUAGE = "de-DE" Then
BarStaticItemInfo.Caption = "Datei nicht vorhanden oder nicht zugreifbar"
Else
BarStaticItemInfo.Caption = "File is not existing or accessible!"
End If
If DocumentViewerMonitor IsNot Nothing Then
DocumentViewerMonitor.Visible = False
End If
Exit Sub
End If
If DocumentViewerMonitor Is Nothing Then
LOGGER.Error("BarButtonItem3: DocumentViewerMonitor is Nothing")
MsgBox("Document viewer is not initialized.", MsgBoxStyle.Critical, "DocView")
Exit Sub
End If
Try
DocumentViewerMonitor.LoadFile_FromPath(oDocPath)
Catch ex As Exception
LOGGER.Error(ex)
BarStaticItemInfo.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
BarStaticItemInfo.Caption = "Error loading document"
DocumentViewerMonitor.Visible = False
MsgBox(ex.Message, MsgBoxStyle.Critical, "Error loading document")
End Try
DocumentViewerMonitor?.LoadFile_FromPath(oDocPath)
'If oDocPath <> "" Then
' If Not Application.OpenForms().OfType(Of frmValidator).Any Then

View File

@@ -479,6 +479,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="ApplicationEvents.vb" />
<Compile Include="ClassCockpit.vb" />
<Compile Include="ClassConfig.vb" />
<Compile Include="ClassConstants.vb" />
<Compile Include="ClassControlCreator.vb" />
@@ -920,6 +921,9 @@
<DependentUpon>frmLoginAdmin.vb</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="frmMain.aa.resx">
<DependentUpon>frmMain.vb</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="frmMain.en.resx">
<DependentUpon>frmMain.vb</DependentUpon>
<SubType>Designer</SubType>