Verbesserung von Logging, Fehlerbehandlung und Caching

Die Änderungen umfassen:
- Zusätzliche Prüfung und Fehlermeldung in `ctrlObjectPropertyDialog`, wenn keine Business Entities gefunden werden.
- Anpassung der Logik in `frmObjectPropertyDialog` zur besseren Zuordnung von LayoutControlItem und BaseEdit.
- Einführung von Thread-Sicherheit für den Cache in `EDMIService` mittels `SyncLock`.
- Erweiterung von Methoden wie `ReturnDatatable`, `ReturnScalarValue` und `ExecuteNonQuery` um Performance-Messung mit `Stopwatch`.
- Vereinheitlichung der Fehlerbehandlung durch konsistente Nutzung von `FaultException`.
- Erweiterung des Loggings für Sessions, Cache-Aktualisierungen und Datenbankoperationen.
- Korrektur der Rückgabe in `GetFileInfoByObjectId` und Verbesserung der Fault-Wrapper-Methoden.
- Bereinigung von redundanten Codezeilen und Kommentaren.
This commit is contained in:
Developer01
2026-09-29 15:49:59 +02:00
parent ab7e063cbe
commit d15d464034
3 changed files with 102 additions and 47 deletions

View File

@@ -85,6 +85,13 @@ Public Class ctrlObjectPropertyDialog
End If End If
' Load Business Entities ' Load Business Entities
Dim oEntityIds = Await GetBusinessEntitiesForObjectId(pObjectId) Dim oEntityIds = Await GetBusinessEntitiesForObjectId(pObjectId)
If oEntityIds.Count = 0 Then
_Logger.Warn("Keine Business Entities für ObjectId {0} gefunden.", pObjectId)
Helper.ShowErrorMessage(New ApplicationException($"Für das Objekt '{pObjectId}' wurden keine Business Entities gefunden."), "LoadObject")
Return False
End If
Dim oActiveEntity = oEntityIds.FirstOrDefault() Dim oActiveEntity = oEntityIds.FirstOrDefault()
Dim oCombobox As RepositoryItemComboBox = DirectCast(cmbEntityId.Edit, RepositoryItemComboBox) Dim oCombobox As RepositoryItemComboBox = DirectCast(cmbEntityId.Edit, RepositoryItemComboBox)

View File

@@ -154,7 +154,8 @@ Public Class frmObjectPropertyDialog
End Sub End Sub
Private Sub BaseEdit_EditValueChanged(sender As Object, e As EventArgs) Private Sub BaseEdit_EditValueChanged(sender As Object, e As EventArgs)
Dim oControl As BaseEdit = sender Dim oControlItem As LayoutControlItem = sender
Dim oControl As BaseEdit = oControlItem.Control
Dim oAttribute As Attribute = oControl.Tag Dim oAttribute As Attribute = oControl.Tag
Dim oValue = oControl.EditValue Dim oValue = oControl.EditValue
Dim oKey = oAttribute.Title Dim oKey = oAttribute.Title
@@ -163,7 +164,6 @@ Public Class frmObjectPropertyDialog
Changes.Item(oKey) = oValue Changes.Item(oKey) = oValue
Else Else
Changes.Add(oAttribute.Title, oValue) Changes.Add(oAttribute.Title, oValue)
End If End If
End Sub End Sub

View File

@@ -1,19 +1,21 @@
Imports System.IO Imports System.Diagnostics
Imports System.IO
Imports System.ServiceModel Imports System.ServiceModel
Imports System.ServiceModel.Description Imports System.ServiceModel.Description
Imports System.Threading
Imports DigitalData.Modules.Database Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Logging
'Imports DigitalData.Modules.
Imports DigitalData.Modules.EDMI Imports DigitalData.Modules.EDMI
Imports DigitalData.Modules.EDMI.API.Rights Imports DigitalData.Modules.EDMI.API.Rights
Imports DigitalData.Services.EDMIService.Messages Imports DigitalData.Modules.Logging
Imports DigitalData.Services.EDMIService.Exceptions Imports DigitalData.Services.EDMIService.Exceptions
Imports DigitalData.Services.EDMIService.Messages
Imports DigitalData.Services.EDMIService.Methods Imports DigitalData.Services.EDMIService.Methods
Imports DigitalData.Services.EDMIService.Methods.Database Imports DigitalData.Services.EDMIService.Methods.Database
Imports DigitalData.Services.EDMIService.Methods.IDB Imports DigitalData.Services.EDMIService.Methods.IDB
<ServiceBehavior(InstanceContextMode:=InstanceContextMode.PerSession)> <ServiceBehavior(InstanceContextMode:=InstanceContextMode.PerSession,
ConcurrencyMode:=ConcurrencyMode.Multiple)>
Public Class EDMIService Public Class EDMIService
Implements IEDMIService Implements IEDMIService
@@ -91,29 +93,29 @@ Public Class EDMIService
_Logger = LogConfig.GetLogger() _Logger = LogConfig.GetLogger()
_IDBHelpers = New IDB.Helpers(LogConfig, MSSQL_IDB) _IDBHelpers = New IDB.Helpers(LogConfig, MSSQL_IDB)
' ── Konfiguration beim ersten Aufruf loggen ─────────────────────────── Dim oEndpointSnapshot = Interlocked.Exchange(Of String)(_ConfiguredEndpoint, String.Empty)
If Not String.IsNullOrEmpty(_ConfiguredEndpoint) Then If Not String.IsNullOrEmpty(oEndpointSnapshot) Then
_Logger.Info("✔ EDMIService configured | Endpoint=[{0}] | MaxCalls=[{1}] | MaxSessions=[{2}] | CPUs=[{3}]", _Logger.Info("✔ EDMIService configured | Endpoint=[{0}] | MaxCalls=[{1}] | MaxSessions=[{2}] | CPUs=[{3}]",
_ConfiguredEndpoint, _ConfiguredMaxCalls, _ConfiguredMaxSessions, Environment.ProcessorCount) oEndpointSnapshot, _ConfiguredMaxCalls, _ConfiguredMaxSessions, Environment.ProcessorCount)
_ConfiguredEndpoint = String.Empty
End If End If
' ─────────────────────────────────────────────────────────────────────
' ── Session registrieren ──────────────────────────────────────────────
_ActiveSessions(oSessionId) = _Username _ActiveSessions(oSessionId) = _Username
BuildUserList() ' ← Neu: Session-Start loggen
_Logger.Debug("Session opened | User=[{0}] | SessionId=[{1}] | ActiveSessions=[{2}]",
_Username, oSessionId, _ActiveSessions.Count)
AddHandler oInstanceContext.Closed, Sub() AddHandler oInstanceContext.Closed, Sub()
Dim oRemoved As String = Nothing Dim oRemoved As String = Nothing
_ActiveSessions.TryRemove(oSessionId, oRemoved) _ActiveSessions.TryRemove(oSessionId, oRemoved)
BuildUserList() _Logger.Debug("Session closed | User=[{0}] | SessionId=[{1}] | ActiveSessions=[{2}]",
_Username, oSessionId, _ActiveSessions.Count)
End Sub End Sub
AddHandler oInstanceContext.Faulted, Sub() AddHandler oInstanceContext.Faulted, Sub()
Dim oRemoved As String = Nothing Dim oRemoved As String = Nothing
_ActiveSessions.TryRemove(oSessionId, oRemoved) _ActiveSessions.TryRemove(oSessionId, oRemoved)
_Logger.Warn("⚠ Session faulted | User=[{0}] | ActiveSessions=[{1}]", _Logger.Warn("⚠ Session faulted | User=[{0}] | SessionId=[{1}] | ActiveSessions=[{2}]",
_Username, _ActiveSessions.Count) _Username, oSessionId, _ActiveSessions.Count)
End Sub End Sub
End Sub End Sub
@@ -199,17 +201,24 @@ Public Class EDMIService
#Region "=== Database ===" #Region "=== Database ==="
Private Shared ReadOnly _CachedTablesLock As New Object()
Private Shared _CachedTablesSnapshot As List(Of String) = Nothing Private Shared _CachedTablesSnapshot As List(Of String) = Nothing
Private Shared _CachedTablesExpiry As DateTime = DateTime.MinValue Private Shared _CachedTablesExpiry As DateTime = DateTime.MinValue
Public Function GetCachedTables() As List(Of String) Implements IEDMIService.GetCachedTables Public Function GetCachedTables() As List(Of String) Implements IEDMIService.GetCachedTables
Try Try
If _CachedTablesSnapshot Is Nothing OrElse DateTime.Now > _CachedTablesExpiry Then SyncLock _CachedTablesLock
_CachedTablesSnapshot = GlobalState.GetCachedTables() If _CachedTablesSnapshot Is Nothing OrElse DateTime.Now > _CachedTablesExpiry Then
_CachedTablesExpiry = DateTime.Now.AddSeconds(30) _Logger.Debug("GetCachedTables: Refreshing cache...")
End If _CachedTablesSnapshot = GlobalState.GetCachedTables()
Return _CachedTablesSnapshot _CachedTablesExpiry = DateTime.Now.AddSeconds(30)
_Logger.Debug("GetCachedTables: Cache refreshed | Count=[{0}] | NextExpiry=[{1}]",
_CachedTablesSnapshot.Count, _CachedTablesExpiry.ToString("HH:mm:ss"))
End If
Return _CachedTablesSnapshot.ToList()
End SyncLock
Catch ex As Exception Catch ex As Exception
_Logger.Error("GetCachedTables failed | User=[{0}] | Error=[{1}]", _Username, ex.Message)
_Logger.Error(ex) _Logger.Error(ex)
Return New List(Of String) Return New List(Of String)
End Try End Try
@@ -231,21 +240,54 @@ Public Class EDMIService
End Function End Function
Public Function ReturnDatatable(pData As GetDatatable.GetDatatableRequest) As GetDatatable.GetDatatableResponse Implements IEDMIService.ReturnDatatable Public Function ReturnDatatable(pData As GetDatatable.GetDatatableRequest) As GetDatatable.GetDatatableResponse Implements IEDMIService.ReturnDatatable
_Logger.Debug("Start of Method [ReturnDatatable]") Dim oWatch = Stopwatch.StartNew()
Dim oGetDatatable As New GetDatatable.GetDatatableMethod(LogConfig, MSSQL_IDB, MSSQL_ECM, GlobalState) Try
Return oGetDatatable.Run(pData) _Logger.Debug("ReturnDatatable | User=[{0}] | DB=[{1}] | SQL=[{2}]",
_Username, pData.NamedDatabase, pData.SqlCommand)
Dim oGetDatatable As New GetDatatable.GetDatatableMethod(LogConfig, MSSQL_IDB, MSSQL_ECM, GlobalState)
Dim oResult = oGetDatatable.Run(pData)
_Logger.Debug("ReturnDatatable completed | User=[{0}] | Rows=[{1}] | Duration=[{2}ms]",
_Username, If(oResult?.Table?.Rows.Count, 0), oWatch.ElapsedMilliseconds)
Return oResult
Catch ex As Exception
_Logger.Error("ReturnDatatable failed | User=[{0}] | Duration=[{1}ms] | Error=[{2}]",
_Username, oWatch.ElapsedMilliseconds, ex.Message)
Throw
End Try
End Function End Function
Public Function ReturnScalarValue(pData As GetScalarValue.GetScalarValueRequest) As GetScalarValue.GetScalarValueResponse Implements IEDMIService.ReturnScalarValue Public Function ReturnScalarValue(pData As GetScalarValue.GetScalarValueRequest) As GetScalarValue.GetScalarValueResponse Implements IEDMIService.ReturnScalarValue
_Logger.Debug("Start of Method [ReturnScalarValue]") Dim oWatch = Stopwatch.StartNew()
Dim oGetScalarValue As New GetScalarValue.GetScalarValueMethod(LogConfig, MSSQL_IDB, MSSQL_ECM, GlobalState) Try
Return oGetScalarValue.Run(pData) _Logger.Debug("ReturnScalarValue | User=[{0}] | DB=[{1}] | SQL=[{2}]",
_Username, pData.NamedDatabase, pData.SqlCommand)
Dim oGetScalarValue As New GetScalarValue.GetScalarValueMethod(LogConfig, MSSQL_IDB, MSSQL_ECM, GlobalState)
Dim oResult = oGetScalarValue.Run(pData)
_Logger.Debug("ReturnScalarValue completed | User=[{0}] | Duration=[{1}ms]",
_Username, oWatch.ElapsedMilliseconds)
Return oResult
Catch ex As Exception
_Logger.Error("ReturnScalarValue failed | User=[{0}] | Duration=[{1}ms] | Error=[{2}]",
_Username, oWatch.ElapsedMilliseconds, ex.Message)
Throw
End Try
End Function End Function
Public Function ExecuteNonQuery(pData As ExecuteNonQuery.ExecuteNonQueryRequest) As ExecuteNonQuery.ExecuteNonQueryResponse Implements IEDMIService.ExecuteNonQuery Public Function ExecuteNonQuery(pData As ExecuteNonQuery.ExecuteNonQueryRequest) As ExecuteNonQuery.ExecuteNonQueryResponse Implements IEDMIService.ExecuteNonQuery
_Logger.Debug("Start of Method [ExecuteNonQuery]") Dim oWatch = Stopwatch.StartNew()
Dim oExecuteNonQuery As New ExecuteNonQuery.ExecuteNonQueryMethod(LogConfig, MSSQL_IDB, MSSQL_ECM, GlobalState) Try
Return oExecuteNonQuery.Run(pData) _Logger.Debug("ExecuteNonQuery | User=[{0}] | DB=[{1}] | SQL=[{2}]",
_Username, pData.NamedDatabase, pData.SqlCommand)
Dim oExecuteNonQuery As New ExecuteNonQuery.ExecuteNonQueryMethod(LogConfig, MSSQL_IDB, MSSQL_ECM, GlobalState)
Dim oResult = oExecuteNonQuery.Run(pData)
_Logger.Debug("ExecuteNonQuery completed | User=[{0}] | Duration=[{1}ms]",
_Username, oWatch.ElapsedMilliseconds)
Return oResult
Catch ex As Exception
_Logger.Error("ExecuteNonQuery failed | User=[{0}] | Duration=[{1}ms] | Error=[{2}]",
_Username, oWatch.ElapsedMilliseconds, ex.Message)
Throw
End Try
End Function End Function
#End Region #End Region
@@ -259,7 +301,7 @@ Public Class EDMIService
Catch ex As FaultException Catch ex As FaultException
_Logger.Error(ex) _Logger.Error(ex)
Throw ex Throw
Catch ex As Exception Catch ex As Exception
_Logger.Error(ex) _Logger.Error(ex)
@@ -276,7 +318,7 @@ Public Class EDMIService
Catch ex As FaultException Catch ex As FaultException
_Logger.Error(ex) _Logger.Error(ex)
Throw ex Throw
Catch ex As Exception Catch ex As Exception
_Logger.Error(ex) _Logger.Error(ex)
@@ -293,7 +335,7 @@ Public Class EDMIService
Catch ex As FaultException Catch ex As FaultException
_Logger.Error(ex) _Logger.Error(ex)
Throw ex Throw
Catch ex As Exception Catch ex As Exception
_Logger.Error(ex) _Logger.Error(ex)
@@ -313,7 +355,7 @@ Public Class EDMIService
Catch ex As FaultException Catch ex As FaultException
_Logger.Error(ex) _Logger.Error(ex)
Throw ex Throw
Catch ex As Exception Catch ex As Exception
_Logger.Error(ex) _Logger.Error(ex)
@@ -330,7 +372,7 @@ Public Class EDMIService
Catch ex As FaultException Catch ex As FaultException
_Logger.Error(ex) _Logger.Error(ex)
Throw ex Throw
Catch ex As Exception Catch ex As Exception
_Logger.Error(ex) _Logger.Error(ex)
@@ -347,7 +389,7 @@ Public Class EDMIService
Catch ex As FaultException Catch ex As FaultException
_Logger.Error(ex) _Logger.Error(ex)
Throw ex Throw
Catch ex As Exception Catch ex As Exception
_Logger.Error(ex) _Logger.Error(ex)
@@ -367,7 +409,7 @@ Public Class EDMIService
Catch ex As FaultException Catch ex As FaultException
_Logger.Error(ex) _Logger.Error(ex)
Throw ex Throw
Catch ex As Exception Catch ex As Exception
_Logger.Error(ex) _Logger.Error(ex)
@@ -384,7 +426,7 @@ Public Class EDMIService
Catch ex As FaultException Catch ex As FaultException
_Logger.Error(ex) _Logger.Error(ex)
Throw ex Throw
Catch ex As Exception Catch ex As Exception
_Logger.Error(ex) _Logger.Error(ex)
@@ -401,7 +443,7 @@ Public Class EDMIService
Catch ex As FaultException Catch ex As FaultException
_Logger.Error(ex) _Logger.Error(ex)
Throw ex Throw
Catch ex As Exception Catch ex As Exception
_Logger.Error(ex) _Logger.Error(ex)
@@ -502,7 +544,7 @@ Public Class EDMIService
Catch ex As FaultException Catch ex As FaultException
_Logger.Error(ex) _Logger.Error(ex)
Throw ex Throw
Catch ex As Exception Catch ex As Exception
_Logger.Error(ex) _Logger.Error(ex)
@@ -522,15 +564,17 @@ Public Class EDMIService
Throw New FaultException(Of ObjectDoesNotExistFault)(oFault, oFault.ErrorMessage) Throw New FaultException(Of ObjectDoesNotExistFault)(oFault, oFault.ErrorMessage)
End If End If
Return New DocumentInfoResponse With { Dim oResult = New DocumentInfoResponse With {
.FileRight = oAccessRight, .FileRight = oAccessRight,
.FullPath = oFullPath .FullPath = oFullPath
} }
_Logger.Debug("End GetFileInfoByObjectId!") _Logger.Debug("End GetFileInfoByObjectId!") ' ← jetzt erreichbar
Return oResult
Catch ex As FaultException Catch ex As FaultException
_Logger.Warn("⚠ GetFileInfoByObjectId: " & ex.Message) _Logger.Warn("⚠ GetFileInfoByObjectId: " & ex.Message)
_Logger.Error(ex) _Logger.Error(ex)
Throw ex Throw
Catch ex As Exception Catch ex As Exception
_Logger.Warn("⚠ GetFileInfoByObjectId: " & ex.Message) _Logger.Warn("⚠ GetFileInfoByObjectId: " & ex.Message)
@@ -550,7 +594,7 @@ Public Class EDMIService
Catch ex As FaultException Catch ex As FaultException
_Logger.Error(ex) _Logger.Error(ex)
Throw ex Throw
Catch ex As Exception Catch ex As Exception
_Logger.Error(ex) _Logger.Error(ex)
@@ -607,13 +651,17 @@ Public Class EDMIService
Private Function GetFault(Exception As Exception) As FaultException Private Function GetFault(Exception As Exception) As FaultException
Dim oMessage = If(Exception?.Message, "Unknown error")
_Logger.Error("Wrapping exception as FaultException | Error=[{0}]", oMessage)
Dim oFault As New UnexpectedErrorFault(Exception) Dim oFault As New UnexpectedErrorFault(Exception)
Return New FaultException(Of UnexpectedErrorFault)(oFault, New FaultReason(oFault.InnerException.Message)) Dim oReason = If(Exception?.InnerException?.Message, oMessage)
Return New FaultException(Of UnexpectedErrorFault)(oFault, New FaultReason(oReason))
End Function End Function
Private Function GetFault(ErrorMessage As String) As FaultException Private Function GetFault(ErrorMessage As String) As FaultException
_Logger.Error("Wrapping error as FaultException | Error=[{0}]", ErrorMessage)
Dim oFault As New UnexpectedErrorFault(New ApplicationException(ErrorMessage)) Dim oFault As New UnexpectedErrorFault(New ApplicationException(ErrorMessage))
Return New FaultException(Of UnexpectedErrorFault)(oFault, New FaultReason(oFault.InnerException.Message)) Return New FaultException(Of UnexpectedErrorFault)(oFault, New FaultReason(ErrorMessage))
End Function End Function
Private Function GetFullPathForObjectId(ObjectId As Long) As String Private Function GetFullPathForObjectId(ObjectId As Long) As String