git_bsmd/bsmd.database/DBManagerAsync.cs

400 lines
15 KiB
C#

// 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<PortArea> _allPortAreaRows;
private static Dictionary<string, PortArea> _allPortAreasByCode;
private static List<LADG_NST2007> _allLADGNST2007Rows;
private static Dictionary<string, LADG_NST2007> _allLADGNST2007ByDescription;
#endregion
#region Properties
public static string ConnectionString { get; set; }
#endregion
#region public methods
public static async Task<int> 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<int> 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<List<MessageCore>> LoadMaerskCoresByIntervalAsync(Dictionary<MessageCore.SearchFilterType, string> 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<MessageCore> 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<MessageCore> 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<MaerskData> 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<MaerskData> 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<List<ValueMapping>> 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<List<WASExemption>> 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<List<HAZPosTemplate>> 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<List<PortArea>> LoadPortAreasAsync(bool forceReload = false)
{
await EnsurePortAreasLoadedAsync(forceReload);
return new List<PortArea>(_allPortAreaRows);
}
public static async Task<Dictionary<string, PortArea>> GetPortAreaDictAsync(bool forceReload = false)
{
await EnsurePortAreasLoadedAsync(forceReload);
return _allPortAreasByCode;
}
public static Dictionary<string, PortArea> GetPortAreaDict(bool forceReload = false)
{
return Task.Run(() => GetPortAreaDictAsync(forceReload)).GetAwaiter().GetResult();
}
public static void InvalidatePortAreaCache()
{
_allPortAreaRows = null;
_allPortAreasByCode = null;
}
public static async Task<List<LADG_NST2007>> LoadLADGNST2007Async(bool forceReload = false)
{
await EnsureLADGNST2007LoadedAsync(forceReload);
return new List<LADG_NST2007>(_allLADGNST2007Rows);
}
public static async Task<Dictionary<string, LADG_NST2007>> GetLADGNST2007DictAsync(bool forceReload = false)
{
await EnsureLADGNST2007LoadedAsync(forceReload);
return _allLADGNST2007ByDescription;
}
public static Dictionary<string, LADG_NST2007> GetLADGNST2007Dict(bool forceReload = false)
{
return Task.Run(() => GetLADGNST2007DictAsync(forceReload)).GetAwaiter().GetResult();
}
public static void InvalidateLADGNST2007Cache()
{
_allLADGNST2007Rows = null;
_allLADGNST2007ByDescription = null;
}
public static async Task<List<AGNT_Template>> 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<List<SERV_Template>> 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<List<WasteDisposalServiceProvider_Template>> 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<PortArea> rows = new List<PortArea>();
if (reader != null)
{
foreach (DatabaseEntity entity in portArea.LoadList(reader))
{
if (entity is PortArea pa)
rows.Add(pa);
}
}
Dictionary<string, PortArea> byCode = new Dictionary<string, PortArea>(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<LADG_NST2007> rows = new List<LADG_NST2007>();
if (reader != null)
{
foreach (DatabaseEntity entity in item.LoadList(reader))
{
if (entity is LADG_NST2007 nst)
rows.Add(nst);
}
}
Dictionary<string, LADG_NST2007> byDescription = new Dictionary<string, LADG_NST2007>(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<SqlDataReader> 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<int> 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<int?> 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
}
}