// Copyright (c) 2023-present schick Informatik // Description: Variant of DBManager that uses async calls using log4net; using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; namespace bsmd.database { public static class DBManagerAsync { #region Fields private static readonly ILog _log = LogManager.GetLogger(typeof(DBManagerAsync)); private static readonly SemaphoreSlim _portAreaLoadLock = new SemaphoreSlim(1, 1); private static readonly SemaphoreSlim _ladgNst2007LoadLock = new SemaphoreSlim(1, 1); private static List _allPortAreaRows; private static Dictionary _allPortAreasByCode; private static List _allLADGNST2007Rows; private static Dictionary _allLADGNST2007ByDescription; #endregion #region Properties public static string ConnectionString { get; set; } #endregion #region public methods public static async Task SaveAsync(DatabaseEntity entity) { SqlCommand cmd = new SqlCommand(); entity.PrepareSave(cmd); int result = await PerformNonQueryAsync(cmd); if (result == 1) entity.IsDirty = false; if ((result == 1) && (entity is PortArea)) InvalidatePortAreaCache(); if ((result == 1) && (entity is LADG_NST2007)) InvalidateLADGNST2007Cache(); return result; } public static async Task DeleteAsync(DatabaseEntity entity) { if (!entity.IsNew) { using (SqlCommand cmd = new SqlCommand()) { entity.PrepareDelete(cmd); int result = await PerformNonQueryAsync(cmd); if ((result == 1) && (entity is PortArea)) InvalidatePortAreaCache(); if ((result == 1) && (entity is LADG_NST2007)) InvalidateLADGNST2007Cache(); return result; } } return 0; } #region convenience loading functions public static async Task> LoadMaerskCoresByIntervalAsync(Dictionary filterDict, bool loadXtraData = false) { SqlCommand cmd = new SqlCommand(); MessageCore aMessageCore = new MessageCore(); aMessageCore.PrepareLoadCommand(cmd, Message.LoadFilter.SEARCH_CORE_FILTERS, filterDict); SqlDataReader reader = await PerformCommandAsync(cmd); return await aMessageCore.LoadListAsync(reader); } public static async Task LoadCoreByVisitIdAsync(string visitId) { SqlCommand cmd = new SqlCommand(); MessageCore aMessageCore = new MessageCore(); aMessageCore.PrepareLoadCommand(cmd, Message.LoadFilter.BY_VISITID, visitId); SqlDataReader reader = await PerformCommandAsync(cmd); List resultList = await aMessageCore.LoadListAsync(reader); MessageCore result = null; if(resultList.Count > 0) { if(resultList.Count > 1) _log.WarnFormat("more than one core found for VISIT-ID {0}", visitId); result = resultList[0]; } return result; } public static async Task LoadMaerskDataForCoreAsync(Guid messageCoreId) { SqlCommand cmd = new SqlCommand(); MaerskData md = new MaerskData(); md.PrepareLoadCommand(cmd, Message.LoadFilter.BY_CORE, messageCoreId); SqlDataReader reader = await PerformCommandAsync(cmd); List resultList = (await md.LoadListAsync(reader)).ConvertAll(x => (MaerskData) x); MaerskData result = null; if(resultList.Count > 0) { if(resultList.Count > 1) _log.WarnFormat("more than one xtra data found for core id {0}", messageCoreId); result = resultList[0]; } return result; } public static async Task> LoadValuesForType(ValueMapping.MappingType mappingType) { SqlCommand cmd = new SqlCommand(); ValueMapping vm = new ValueMapping(); vm.PrepareLoadCommand(cmd, Message.LoadFilter.BY_TYPE, mappingType); SqlDataReader reader = await PerformCommandAsync(cmd); return (await vm.LoadListAsync(reader)).ConvertAll(x => (ValueMapping)x); } public static async Task> LoadWASExemptionsAsync() { SqlCommand cmd = new SqlCommand(); WASExemption was = new WASExemption(); was.PrepareLoadCommand(cmd, Message.LoadFilter.ALL); SqlDataReader reader = await PerformCommandAsync(cmd); return (await was.LoadListAsync(reader)).ConvertAll(x => (WASExemption)x); } public static async Task> LoadHAZTemplatesAsync() { SqlCommand cmd = new SqlCommand(); HAZPosTemplate hpt = new HAZPosTemplate(); hpt.PrepareLoadCommand(cmd, Message.LoadFilter.ALL); SqlDataReader reader = await PerformCommandAsync(cmd); return (await hpt.LoadListAsync(reader)).ConvertAll(x => (HAZPosTemplate)x); } public static async Task> LoadPortAreasAsync(bool forceReload = false) { await EnsurePortAreasLoadedAsync(forceReload); return new List(_allPortAreaRows); } public static async Task> GetPortAreaDictAsync(bool forceReload = false) { await EnsurePortAreasLoadedAsync(forceReload); return _allPortAreasByCode; } public static Dictionary GetPortAreaDict(bool forceReload = false) { return Task.Run(() => GetPortAreaDictAsync(forceReload)).GetAwaiter().GetResult(); } public static void InvalidatePortAreaCache() { _allPortAreaRows = null; _allPortAreasByCode = null; } public static async Task> LoadLADGNST2007Async(bool forceReload = false) { await EnsureLADGNST2007LoadedAsync(forceReload); return new List(_allLADGNST2007Rows); } public static async Task> GetLADGNST2007DictAsync(bool forceReload = false) { await EnsureLADGNST2007LoadedAsync(forceReload); return _allLADGNST2007ByDescription; } public static Dictionary GetLADGNST2007Dict(bool forceReload = false) { return Task.Run(() => GetLADGNST2007DictAsync(forceReload)).GetAwaiter().GetResult(); } public static void InvalidateLADGNST2007Cache() { _allLADGNST2007Rows = null; _allLADGNST2007ByDescription = null; } public static async Task> GetAGNTTemplatesAsync() { SqlCommand cmd = new SqlCommand(); AGNT_Template at = new AGNT_Template(); at.PrepareLoadCommand(cmd, Message.LoadFilter.ALL); SqlDataReader reader = await PerformCommandAsync(cmd); return (await at.LoadListAsync(reader)).ConvertAll(x => (AGNT_Template)x); } public static async Task> GetSERVTemplatesAsync() { SqlCommand cmd = new SqlCommand(); SERV_Template st = new SERV_Template(); st.PrepareLoadCommand(cmd, Message.LoadFilter.ALL); SqlDataReader reader = await PerformCommandAsync(cmd); return (await st.LoadListAsync(reader)).ConvertAll(x => (SERV_Template)x); } public static async Task> GetWasteDisposalServiceProviderTemplatesAsync() { SqlCommand cmd = new SqlCommand(); WasteDisposalServiceProvider_Template wdsp_t = new WasteDisposalServiceProvider_Template(); wdsp_t.PrepareLoadCommand(cmd, Message.LoadFilter.ALL); SqlDataReader reader = await PerformCommandAsync(cmd); return (await wdsp_t.LoadListAsync(reader)).ConvertAll(x => (WasteDisposalServiceProvider_Template)x); } #endregion #endregion #region private helpers private static async Task EnsurePortAreasLoadedAsync(bool forceReload) { if (forceReload) InvalidatePortAreaCache(); if ((_allPortAreaRows != null) && (_allPortAreasByCode != null)) return; await _portAreaLoadLock.WaitAsync(); try { if ((_allPortAreaRows != null) && (_allPortAreasByCode != null)) return; SqlCommand cmd = new SqlCommand(); PortArea portArea = new PortArea(); portArea.PrepareLoadCommand(cmd, Message.LoadFilter.ALL); SqlDataReader reader = await PerformCommandAsync(cmd); List rows = new List(); if (reader != null) { foreach (DatabaseEntity entity in portArea.LoadList(reader)) { if (entity is PortArea pa) rows.Add(pa); } } Dictionary byCode = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (PortArea pa in rows) { if (!pa.Code.IsNullOrEmpty()) byCode[pa.Code] = pa; } _allPortAreaRows = rows; _allPortAreasByCode = byCode; } finally { _portAreaLoadLock.Release(); } } private static async Task EnsureLADGNST2007LoadedAsync(bool forceReload) { if (forceReload) InvalidateLADGNST2007Cache(); if ((_allLADGNST2007Rows != null) && (_allLADGNST2007ByDescription != null)) return; await _ladgNst2007LoadLock.WaitAsync(); try { if ((_allLADGNST2007Rows != null) && (_allLADGNST2007ByDescription != null)) return; SqlCommand cmd = new SqlCommand(); LADG_NST2007 item = new LADG_NST2007(); item.PrepareLoadCommand(cmd, Message.LoadFilter.ALL); SqlDataReader reader = await PerformCommandAsync(cmd); List rows = new List(); if (reader != null) { foreach (DatabaseEntity entity in item.LoadList(reader)) { if (entity is LADG_NST2007 nst) rows.Add(nst); } } Dictionary byDescription = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (LADG_NST2007 nst in rows) { if (!nst.Description.IsNullOrEmpty()) byDescription[nst.Description] = nst; } _allLADGNST2007Rows = rows; _allLADGNST2007ByDescription = byDescription; } finally { _ladgNst2007LoadLock.Release(); } } #endregion #region async DB access methods internal static async Task PerformCommandAsync(SqlCommand cmd) { SqlDataReader reader = null; try { SqlConnection connection = new SqlConnection(ConnectionString); await connection.OpenAsync(); cmd.Connection = connection; reader = await cmd.ExecuteReaderAsync(); } catch (SqlException ex) { Trace.WriteLine("SQL Exception:" + ex.Message); _log.Error("Error performing command", ex); _log.DebugFormat("Query: {0}", cmd.CommandText); _log.Debug("Parameters:"); for (int i = 0; i < cmd.Parameters.Count; i++) { _log.DebugFormat("{0}:{1}", cmd.Parameters[i].ParameterName, cmd.Parameters[i].Value); } } return reader; } internal static async Task PerformNonQueryAsync(SqlCommand cmd) { int result = -1; // await _asyncSemaphore.WaitAsync(); try { using (SqlConnection connection = new SqlConnection(ConnectionString)) { await connection.OpenAsync(); cmd.Connection = connection; result = await cmd.ExecuteNonQueryAsync(); } } catch (SqlException ex) { Trace.WriteLine("SQL Exception:" + ex.Message); _log.Error("Error performing command", ex); _log.DebugFormat("Query: {0}", cmd.CommandText); _log.Debug("Parameters:"); for (int i = 0; i < cmd.Parameters.Count; i++) { _log.DebugFormat("{0}:{1}", cmd.Parameters[i].ParameterName, cmd.Parameters[i].Value); } } return result; } internal static async Task PerformReadIntQueryAsync(SqlCommand cmd) { int? result = null; try { using (SqlConnection connection = new SqlConnection(ConnectionString)) { cmd.Connection = connection; object r = await cmd.ExecuteScalarAsync(); if (r == null) { result = null; } else if (r == DBNull.Value) { result = null; } else { result = (int)r; } } } catch (SqlException ex) { _log.Error("Error performing command", ex); _log.DebugFormat("Query: {0}", cmd.CommandText); _log.Debug("Parameters:"); for (int i = 0; i < cmd.Parameters.Count; i++) { _log.DebugFormat("{0}:{1}", cmd.Parameters[i].ParameterName, cmd.Parameters[i].Value); } } return result; } #endregion } }