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
' Load Business Entities
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 oCombobox As RepositoryItemComboBox = DirectCast(cmbEntityId.Edit, RepositoryItemComboBox)

View File

@@ -154,7 +154,8 @@ Public Class frmObjectPropertyDialog
End Sub
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 oValue = oControl.EditValue
Dim oKey = oAttribute.Title
@@ -163,7 +164,6 @@ Public Class frmObjectPropertyDialog
Changes.Item(oKey) = oValue
Else
Changes.Add(oAttribute.Title, oValue)
End If
End Sub

View File

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