diff --git a/GUIs.Common/ObjectPropertyDialog/ctrlObjectPropertyDialog.vb b/GUIs.Common/ObjectPropertyDialog/ctrlObjectPropertyDialog.vb index 1cb3e20a..2a73ac0a 100644 --- a/GUIs.Common/ObjectPropertyDialog/ctrlObjectPropertyDialog.vb +++ b/GUIs.Common/ObjectPropertyDialog/ctrlObjectPropertyDialog.vb @@ -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) diff --git a/GUIs.Common/ObjectPropertyDialog/frmObjectPropertyDialog.vb b/GUIs.Common/ObjectPropertyDialog/frmObjectPropertyDialog.vb index b081817b..0a6ab74d 100644 --- a/GUIs.Common/ObjectPropertyDialog/frmObjectPropertyDialog.vb +++ b/GUIs.Common/ObjectPropertyDialog/frmObjectPropertyDialog.vb @@ -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 diff --git a/Service.EDMIService/EDMIService.vb b/Service.EDMIService/EDMIService.vb index 4992bcc7..5a7da31e 100644 --- a/Service.EDMIService/EDMIService.vb +++ b/Service.EDMIService/EDMIService.vb @@ -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 - + 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