Refactoring PortArea:

- Hinzufügen eines Editors im Admin-Bereich
- Entfernen der PortArea Daten aus SQLite und den Zugriffsklassen
- Ersetzen aller Zugriffe durch Daten aus der DB (DBManagerAsync)
This commit is contained in:
Daniel Schick 2026-02-19 10:42:36 +01:00
parent 96947af10c
commit 90a4915683
18 changed files with 584 additions and 208 deletions

View File

@ -91,7 +91,7 @@ namespace ENI2
// Preload validation fields
List<ValidationField> vFields = bsmd.database.ValidationRule.ValidationFields;
RuleEngine.RegisterLocodeChecker(Util.GlobalStructures.IsValidLocode);
RuleEngine.RegisterPortAreaChecker(LocalizedLookup.PortAreaExists);
RuleEngine.RegisterPortAreaChecker(bsmd.database.PortArea.PortAreaExists);
RuleEngine.RegisterNationalityChecker(LocalizedLookup.CheckNationality);
// Register expandable Properties

View File

@ -0,0 +1,124 @@
<UserControl x:Class="ENI2.Controls.PortAreaControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ENI2.Controls"
xmlns:util="clr-namespace:ENI2.Util"
xmlns:p="clr-namespace:ENI2.Properties"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="1000">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Content="Port areas" />
<GroupBox Header="" Grid.Row="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120" />
<ColumnDefinition Width="120" />
<ColumnDefinition Width="120" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button x:Name="buttonSave" Grid.Column="0" Margin="2" Content="Save all changes" Click="buttonSave_Click" />
<Button x:Name="buttonAdd" Grid.Column="1" Margin="2" Content="Add new" Click="buttonAdd_Click" />
<Button x:Name="buttonImport" Grid.Column="2" Margin="2" Content="{x:Static p:Resources.textImportFromExcel}" Click="buttonImport_Click" />
</Grid>
<local:ENIDataGrid Grid.Row="1" Margin="2,8,2,2" x:Name="dataGridPortAreas" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"
SelectionMode="Extended" AutoGenerateColumns="False" CanUserAddRows="False"
CellEditEnding="dataGridPortAreas_CellEditEnding">
<DataGrid.Columns>
<DataGridTextColumn Header="Country" Width="80">
<DataGridTextColumn.Binding>
<Binding Path="Country" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<util:StringValidationRule MaxLength="10" />
</Binding.ValidationRules>
</Binding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
<DataGridTextColumn Header="Locode" Width="90">
<DataGridTextColumn.Binding>
<Binding Path="Locode" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<util:StringValidationRule MaxLength="5" />
</Binding.ValidationRules>
</Binding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
<DataGridTextColumn Header="Port" Width="140">
<DataGridTextColumn.Binding>
<Binding Path="Port" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<util:StringValidationRule MaxLength="255" />
</Binding.ValidationRules>
</Binding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
<DataGridTextColumn Header="Code" Width="90">
<DataGridTextColumn.Binding>
<Binding Path="Code" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<util:StringValidationRule MaxLength="10" />
</Binding.ValidationRules>
</Binding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
<DataGridTextColumn Header="Name" Width="2*">
<DataGridTextColumn.Binding>
<Binding Path="Name" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<util:StringValidationRule MaxLength="255" />
</Binding.ValidationRules>
</Binding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
<DataGridTextColumn Header="Agency" Width="2*">
<DataGridTextColumn.Binding>
<Binding Path="Agency" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<util:StringValidationRule MaxLength="255" />
</Binding.ValidationRules>
</Binding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
<DataGridTextColumn Header="Berth" Width="2*">
<DataGridTextColumn.Binding>
<Binding Path="Berth" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<util:StringValidationRule MaxLength="255" />
</Binding.ValidationRules>
</Binding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
<DataGridTextColumn Header="Ships" Width="2*">
<DataGridTextColumn.Binding>
<Binding Path="Ships" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<util:StringValidationRule MaxLength="255" />
</Binding.ValidationRules>
</Binding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
<DataGridTextColumn Header="Remarks" Width="2*">
<DataGridTextColumn.Binding>
<Binding Path="Remarks" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<util:StringValidationRule MaxLength="255" />
</Binding.ValidationRules>
</Binding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
</DataGrid.Columns>
</local:ENIDataGrid>
</Grid>
</GroupBox>
</Grid>
</UserControl>

View File

@ -0,0 +1,142 @@
using bsmd.database;
using ENI2.Excel;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace ENI2.Controls
{
/// <summary>
/// Interaction logic for PortAreaControl.xaml
/// </summary>
public partial class PortAreaControl : UserControl
{
private readonly ObservableCollection<PortArea> _portAreas = new ObservableCollection<PortArea>();
public PortAreaControl()
{
InitializeComponent();
this.dataGridPortAreas.ItemsSource = _portAreas;
var view = CollectionViewSource.GetDefaultView(_portAreas);
view.SortDescriptions.Add(new SortDescription(nameof(PortArea.Locode), ListSortDirection.Ascending));
view.SortDescriptions.Add(new SortDescription(nameof(PortArea.Code), ListSortDirection.Ascending));
_ = LoadPortAreasAsync();
this.dataGridPortAreas.ContextMenu = new ContextMenu();
MenuItem addItem = new MenuItem
{
Header = Properties.Resources.textAdd,
Icon = new System.Windows.Controls.Image { Source = new System.Windows.Media.Imaging.BitmapImage(new Uri("pack://application:,,,/Resources/add.png")) }
};
addItem.Click += AddItem_Click;
this.dataGridPortAreas.ContextMenu.Items.Add(addItem);
MenuItem delItem = new MenuItem
{
Header = Properties.Resources.textDelete,
Icon = new System.Windows.Controls.Image { Source = new System.Windows.Media.Imaging.BitmapImage(new Uri("pack://application:,,,/Resources/delete.png")) }
};
delItem.Click += DelItem_Click;
this.dataGridPortAreas.ContextMenu.Items.Add(delItem);
}
private async Task LoadPortAreasAsync()
{
List<PortArea> items = await DBManagerAsync.LoadPortAreasAsync(true);
foreach (PortArea item in items)
{
_portAreas.Add(item);
}
}
private void buttonSave_Click(object sender, RoutedEventArgs e)
{
_ = SavePortAreasAsync();
}
private void buttonAdd_Click(object sender, RoutedEventArgs e)
{
AddNewPortArea();
}
private void buttonImport_Click(object sender, RoutedEventArgs e)
{
var imported = ExcelLocalImportHelper.ImportPortAreas();
foreach (var item in imported)
{
_portAreas.Add(item);
}
}
private void dataGridPortAreas_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
if (e.Row?.Item is PortArea portArea)
{
portArea.IsDirty = true;
}
}
private void AddItem_Click(object sender, RoutedEventArgs e)
{
AddNewPortArea();
}
private async void DelItem_Click(object sender, RoutedEventArgs e)
{
if (this.dataGridPortAreas.SelectedItems.Count > 0)
{
if (MessageBox.Show("Are you sure to delete the selected values?", Properties.Resources.textConfirmation, MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) ==
MessageBoxResult.Yes)
{
var selectedItems = new List<PortArea>();
foreach (PortArea item in this.dataGridPortAreas.SelectedItems)
selectedItems.Add(item);
foreach (PortArea item in selectedItems)
{
int result = await DBManagerAsync.DeleteAsync(item);
if (result == 1 || item.IsNew)
{
_portAreas.Remove(item);
}
}
}
}
}
private void AddNewPortArea()
{
var item = new PortArea
{
IsDirty = true
};
_portAreas.Add(item);
this.dataGridPortAreas.SelectedItem = item;
this.dataGridPortAreas.ScrollIntoView(item);
}
private async Task SavePortAreasAsync()
{
int totalSaves = 0;
foreach (PortArea item in _portAreas)
{
if (item.IsNew || item.IsDirty)
{
totalSaves += await DBManagerAsync.SaveAsync(item);
}
}
if (totalSaves > 0)
{
MessageBox.Show($"{totalSaves} port areas saved", "Success", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
}
}

View File

@ -123,7 +123,7 @@ namespace ENI2.DetailViewControls
_infoMessage.Elements.Add(info);
}
portAreas = LocalizedLookup.getPortAreasForLocode(this.Core.PoC);
portAreas = PortArea.getPortAreasForLocode(this.Core.PoC);
this.comboBoxPortArea.ItemsSource = portAreas;
this.comboBoxShippingArea.ItemsSource = shippingAreas;

View File

@ -334,6 +334,9 @@
<Compile Include="Controls\HazardMaterialControl.xaml.cs">
<DependentUpon>HazardMaterialControl.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\PortAreaControl.xaml.cs">
<DependentUpon>PortAreaControl.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\WASExemptionsControl.xaml.cs">
<DependentUpon>WASExemptionsControl.xaml</DependentUpon>
</Compile>
@ -660,6 +663,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\PortAreaControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\WASExemptionsControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>

View File

@ -19,7 +19,7 @@ namespace ENI2.EditControls
#region Fields
private readonly string _poc = null;
private List<PortAreaInfo> _portAreas;
private List<PortArea> _portAreas;
private static readonly object filterLock = new object();
#endregion
@ -44,21 +44,29 @@ namespace ENI2.EditControls
private void Window_Loaded(object sender, RoutedEventArgs e)
{
if(LocalizedLookup.getPortAreaInfos().ContainsKey(this._poc))
_portAreas = LocalizedLookup.getPortAreaInfos()[this._poc];
_portAreas = new List<PortArea>();
List<PortArea> items = DBManagerAsync.LoadPortAreasAsync().Result;
foreach (var item in items) {
if (item.Locode == _poc)
{
_portAreas.Add(item);
}
}
this.labelLocode.Content = this._poc;
}
private void comboBoxType_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
if (this.listBoxAreas.SelectedItem is PortAreaInfo pai)
if (this.listBoxAreas.SelectedItem is PortArea pai)
{
this.textBlockAgency.Text = pai.Agency;
this.textBlockBerth.Text = pai.Berth;
this.textBlockPortArea.Text = pai.PortArea;
this.textBlockPortArea.Text = pai.Name;
this.textBlockShips.Text = pai.Ships;
this.textBlockRemarks.Text = pai.Remark;
this.SelectedArea = pai.PortAreaCode;
this.textBlockRemarks.Text = pai.Remarks;
this.SelectedArea = pai.Code;
}
}
@ -68,13 +76,16 @@ namespace ENI2.EditControls
if (_portAreas == null) return;
lock (filterLock)
{
IEnumerable<PortAreaInfo> filtered = _portAreas;
IEnumerable<PortArea> filtered = _portAreas;
if (searchText.Length > 0)
{
filtered = _portAreas.Where(elem => (elem.Remark != null && elem.Remark.ToUpperInvariant().Contains(searchText.ToUpperInvariant())) ||
filtered = _portAreas.Where(elem =>
(elem.Remarks != null && elem.Remarks.ToUpperInvariant().Contains(searchText.ToUpperInvariant())) ||
(elem.Agency != null && elem.Agency.ToUpperInvariant().Contains(searchText.ToUpperInvariant())) ||
(elem.Berth != null && elem.Berth.ToUpperInvariant().Contains(searchText.ToUpperInvariant())) ||
(elem.PortArea != null && elem.PortArea.ToUpperInvariant().Contains(searchText.ToUpperInvariant())));
(elem.Ships != null && elem.Ships.ToUpperInvariant().Contains(searchText.ToUpperInvariant())) ||
(elem.Name != null && elem.Name.ToUpperInvariant().Contains(searchText.ToUpperInvariant())) ||
(elem.Code != null && elem.Code.ToUpperInvariant().Contains(searchText.ToUpperInvariant())));
}
this.listBoxAreas.ItemsSource = filtered;
}

View File

@ -1139,7 +1139,7 @@ namespace ENI2.Excel
info.FumigatedBulkCargoBool = reader.ReadCellAsBool("port message", "C20");
info.DeplacementSummerDraught_TNE = reader.ReadCellAsDecimal("port message", "C21");
string portArea = reader.ReadCellAsText("port message", "C22")?.Trim().ToUpper();
if (!portArea.IsNullOrEmpty() && DBManager.Instance.GetPortAreaDict().ContainsKey(portArea))
if (!portArea.IsNullOrEmpty() && DBManagerAsync.GetPortAreaDict().ContainsKey(portArea))
info.PortArea = portArea;
else
info.PortArea = "";

View File

@ -504,6 +504,79 @@ namespace ENI2.Excel
#endregion
#region Port Areas Import from Excel
public static List<PortArea> ImportPortAreas()
{
OpenFileDialog ofd = new OpenFileDialog
{
Filter = "Excel Files|*.xls;*.xlsx"
};
if (ofd.ShowDialog() ?? false)
{
try
{
using (var stream = new FileStream(ofd.FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var workbook = new XLWorkbook(stream))
{
var worksheet = workbook.Worksheet(1);
var range = worksheet.RangeUsed();
var rows = range.RowsUsed().Skip(1); // header row
List<PortArea> items = new List<PortArea>();
foreach (var row in rows)
{
if (row.Cell(1).IsEmpty() &&
row.Cell(2).IsEmpty() &&
row.Cell(3).IsEmpty() &&
row.Cell(4).IsEmpty() &&
row.Cell(5).IsEmpty())
continue;
PortArea pa = new PortArea
{
IsDirty = true
};
if (!row.Cell(1).IsEmpty())
pa.Country = Truncate(row.Cell(1).GetString().Trim(), 10);
if (!row.Cell(2).IsEmpty())
pa.Locode = Truncate(row.Cell(2).GetString().Trim(), 5);
if (!row.Cell(3).IsEmpty())
pa.Port = Truncate(row.Cell(3).GetString().Trim(), 255);
if (!row.Cell(4).IsEmpty())
pa.Code = Truncate(row.Cell(4).GetString().Trim(), 10);
if (!row.Cell(5).IsEmpty())
pa.Name = Truncate(row.Cell(5).GetString().Trim(), 255);
if (!row.Cell(6).IsEmpty())
pa.Agency = Truncate(row.Cell(6).GetString().Trim(), 255);
if (!row.Cell(7).IsEmpty())
pa.Berth = Truncate(row.Cell(7).GetString().Trim(), 255);
if (!row.Cell(8).IsEmpty())
pa.Ships = Truncate(row.Cell(8).GetString().Trim(), 255);
if (!row.Cell(9).IsEmpty())
pa.Remarks = Truncate(row.Cell(9).GetString().Trim(), 255);
items.Add(pa);
}
return items;
}
}
catch (Exception ex)
{
MessageBox.Show("Error reading Excel: " + ex.Message, Properties.Resources.textCaptionError,
MessageBoxButton.OK, MessageBoxImage.Error);
}
}
return new List<PortArea>();
}
#endregion
private static string Truncate(string value, int maxLength)
{
if (value == null)

View File

@ -956,7 +956,7 @@ namespace ENI2.Excel
ExcelUtil.ScanMessage(info, reader);
string portArea = reader.ReadText("INFO.PortArea")?.ToUpper();
if (!portArea.IsNullOrEmpty() && DBManager.Instance.GetPortAreaDict().ContainsKey(portArea))
if (!portArea.IsNullOrEmpty() && DBManagerAsync.GetPortAreaDict().ContainsKey(portArea))
{
info.PortArea = portArea;
}

View File

@ -16,7 +16,6 @@ namespace ENI2
private static readonly SQLiteConnection _con;
private const string _locode_DB_NAME = "db.sqlite";
private static Dictionary<string, string> _nationalities = null;
private static Dictionary<string, List<PortAreaInfo>> _portAreaInfos = null;
static LocalizedLookup()
{
@ -43,36 +42,6 @@ namespace ENI2
return result;
}
public static Dictionary<string, string> getPortAreasForLocode(string locode)
{
Dictionary<string, string> result = new Dictionary<string, string>();
string query = string.Format("SELECT Code, PortArea FROM INFO_PortArea WHERE Locode = '{0}' ORDER BY PortArea", locode);
SQLiteCommand cmd = new SQLiteCommand(query, _con);
IDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
string code = null;
string portarea = null;
if (!reader.IsDBNull(0)) code = reader.GetString(0);
if (!reader.IsDBNull(1)) portarea = reader.GetString(1);
if ((code != null) && (portarea != null))
{
result[code] = string.Format("{0}-{1}", code, portarea);
}
}
reader.Close();
return result;
}
public static bool PortAreaExists(string locode, string portArea)
{
if (locode.IsNullOrEmpty() || portArea.IsNullOrEmpty()) return false;
string query = string.Format("SELECT COUNT(*) FROM INFO_PortArea WHERE Locode = '{0}' AND Code = '{1}'", locode, portArea);
SQLiteCommand cmd = new SQLiteCommand(query, _con);
long numResults = (long)cmd.ExecuteScalar();
return numResults > 0;
}
public static bool CheckNationality(string nationality)
{
if (nationality.IsNullOrEmpty()) return false;
@ -298,43 +267,5 @@ namespace ENI2
reader.Close();
return result;
}
public static Dictionary<string, List<PortAreaInfo>> getPortAreaInfos()
{
int cnt = 0;
if (_portAreaInfos == null)
{
_portAreaInfos = new Dictionary<string, List<PortAreaInfo>>();
string query = @"SELECT Locode, Agentur, Schiffe, Liegeplatz, Hafengebiet, `Hafengebiet-Code`, Bemerkungen from INFO_PortArea_Helper";
SQLiteCommand cmd = new SQLiteCommand(query, _con);
IDataReader reader = cmd.ExecuteReader();
while(reader.Read())
{
PortAreaInfo pai = new PortAreaInfo();
if (reader.IsDBNull(0)) continue;
pai.Locode = reader.GetString(0);
if (!reader.IsDBNull(1))
pai.Agency = reader.GetString(1);
if (!reader.IsDBNull(2))
pai.Ships = reader.GetString(2);
if (!reader.IsDBNull(3))
pai.Berth = reader.GetString(3);
if (!reader.IsDBNull(4))
pai.PortArea = reader.GetString(4);
if (!reader.IsDBNull(5))
pai.PortAreaCode = reader.GetString(5);
if (!reader.IsDBNull(6))
pai.Remark = reader.GetString(6);
if (!_portAreaInfos.ContainsKey(pai.Locode))
{
_portAreaInfos[pai.Locode] = new List<PortAreaInfo>();
}
_portAreaInfos[pai.Locode].Add(pai);
cnt++;
}
}
return _portAreaInfos;
}
}
}

View File

@ -108,6 +108,11 @@
<Image Source="Resources/sign_warning.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem x:Name="menuItemPortAreas" Header="Port areas" Click="radioButton_Click">
<MenuItem.Icon>
<Image Source="Resources/anchor.png" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
<MenuItem x:Name="menuItemMaersk" Header="{x:Static p:Resources.textPOLists}" Click="radioButton_Click" Visibility="Hidden" />
<MenuItem x:Name="menuItemValueMappings" Header="{x:Static p:Resources.textExcelValueMappings}" Click="radioButton_Click" Visibility="Hidden" />

View File

@ -42,6 +42,7 @@ namespace ENI2
private EasyPeasyControl easyPeasyControl;
private WASExemptionsControl wasExemptionsControl;
private HazardMaterialControl hazardMaterialControl;
private PortAreaControl portAreaControl;
private bool dbConnected;
private readonly ScaleTransform _transform = new ScaleTransform(1.0, 1.0);
@ -351,6 +352,14 @@ namespace ENI2
}
this.rootContainer.Children.Add(this.hazardMaterialControl);
}
else if (sender == this.menuItemPortAreas)
{
if (this.portAreaControl == null)
{
this.portAreaControl = new PortAreaControl();
}
this.rootContainer.Children.Add(this.portAreaControl);
}
}
private void buttonCompareSheets_Click(object sender, RoutedEventArgs ev)

View File

@ -108,7 +108,7 @@ namespace ENI2.SheetDisplayControls
this.dataGridCallPurposes.CreateRequested += DataGridCallPurposes_CreateRequested;
this.dataGridCallPurposes.DeleteRequested += DataGridCallPurposes_DeleteRequested;
portAreas = LocalizedLookup.getPortAreasForLocode(this.Core.PoC);
portAreas = PortArea.getPortAreasForLocode(this.Core.PoC);
this.comboBoxPortArea.ItemsSource = portAreas;
this.comboBoxPortArea.DataContext = this._info;
this.textRequestedPostionInPortOfCall.DataContext = this._info;

View File

@ -30,7 +30,6 @@ namespace bsmd.database
private static DBManager _instance;
private static readonly ILog _log = LogManager.GetLogger(typeof(DBManager));
private static Dictionary<Guid, ReportingParty> allReportingParties;
private static Dictionary<string, PortArea> allPortAreas;
private readonly object _lock = new object();
private bool _closeConnectionAfterUse = false;
private readonly List<string> truncatedFieldCollection = new List<string>();
@ -93,6 +92,7 @@ namespace bsmd.database
_con = new SqlConnection(dbConnectionString);
_con.Open();
this.ConnectionString = dbConnectionString;
DBManagerAsync.ConnectionString = dbConnectionString;
return true;
}
catch (Exception ex)
@ -109,6 +109,7 @@ namespace bsmd.database
_con = new SqlConnection(dbConnectionString);
await _con.OpenAsync();
this.ConnectionString = dbConnectionString;
DBManagerAsync.ConnectionString = dbConnectionString;
return true;
}
catch(Exception ex)
@ -440,19 +441,7 @@ namespace bsmd.database
public Dictionary<string, PortArea> GetPortAreaDict()
{
if(DBManager.allPortAreas == null)
{
PortArea pa = new PortArea();
SqlCommand cmd = new SqlCommand();
pa.PrepareLoadCommand(cmd, Message.LoadFilter.ALL);
SqlDataReader reader = this.PerformCommand(cmd);
List<DatabaseEntity> portAreas = pa.LoadList(reader);
DBManager.allPortAreas = new Dictionary<string, PortArea>();
foreach (PortArea aPa in portAreas.Cast<PortArea>())
DBManager.allPortAreas[aPa.Code] = aPa; // TODO da gibt es doppelte Einträge
}
return DBManager.allPortAreas;
return DBManagerAsync.GetPortAreaDict();
}
public DatabaseEntity GetMessageById(Guid id)
@ -648,7 +637,7 @@ namespace bsmd.database
this.LogNonQueryResult(cmd.CommandText, queryResult);
this.CreateEntityHistoryEntry(entity);
if (entity is PortArea)
DBManager.allPortAreas = null;
DBManagerAsync.InvalidatePortAreaCache();
if (this._closeConnectionAfterUse) this.Disconnect();
}
@ -665,7 +654,7 @@ namespace bsmd.database
}
}
if (entity is PortArea)
DBManager.allPortAreas = null;
DBManagerAsync.InvalidatePortAreaCache();
if (this._closeConnectionAfterUse) this.Disconnect();
}

View File

@ -16,6 +16,9 @@ namespace bsmd.database
#region Fields
private static readonly ILog _log = LogManager.GetLogger(typeof(DBManagerAsync));
private static readonly SemaphoreSlim _portAreaLoadLock = new SemaphoreSlim(1, 1);
private static List<PortArea> _allPortAreaRows;
private static Dictionary<string, PortArea> _allPortAreasByCode;
#endregion
@ -33,6 +36,8 @@ namespace bsmd.database
entity.PrepareSave(cmd);
int result = await PerformNonQueryAsync(cmd);
if (result == 1) entity.IsDirty = false;
if ((result == 1) && (entity is PortArea))
InvalidatePortAreaCache();
return result;
}
@ -43,7 +48,10 @@ namespace bsmd.database
using (SqlCommand cmd = new SqlCommand())
{
entity.PrepareDelete(cmd);
return await PerformNonQueryAsync(cmd);
int result = await PerformNonQueryAsync(cmd);
if ((result == 1) && (entity is PortArea))
InvalidatePortAreaCache();
return result;
}
}
return 0;
@ -121,6 +129,29 @@ namespace bsmd.database
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<AGNT_Template>> GetAGNTTemplatesAsync()
{
SqlCommand cmd = new SqlCommand();
@ -153,6 +184,55 @@ namespace bsmd.database
#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();
}
}
#endregion
#region async DB access methods
internal static async Task<SqlDataReader> PerformCommandAsync(SqlCommand cmd)

View File

@ -234,33 +234,4 @@ namespace bsmd.database
}
#region class PortAreaInfo
/// <summary>
/// simple helper class container to map support data from sqlite lookup db
/// </summary>
public class PortAreaInfo
{
public string Locode { get; set; }
public string Agency { get; set; }
public string Ships { get; set; }
public string Berth { get; set; }
public string PortArea { get; set; }
public string PortAreaCode { get; set; }
public string Remark { get; set; }
public override string ToString()
{
return string.Format("{0} ({1})", PortArea, Berth);
}
}
#endregion
}

View File

@ -1,5 +1,5 @@
// Copyright (c) 2015-2017 schick Informatik
// Description:
// Copyright (c) 2015-.. schick Informatik
// Description: DB entity for port areas
using System;
using System.Collections.Generic;
@ -52,7 +52,41 @@ namespace bsmd.database
#endregion
#region public static methods
public static bool PortAreaExists(string locode, string code)
{
bool result = false;
if(DBManagerAsync.GetPortAreaDict().TryGetValue(code, out PortArea portArea))
{
if (portArea.Locode == locode)
{
result = true;
}
}
return result;
}
public static Dictionary<string, string> getPortAreasForLocode(string locode)
{
Dictionary<string, string> result = new Dictionary<string, string>();
List<PortArea> portAreas = DBManagerAsync.LoadPortAreasAsync().Result;
foreach (PortArea portArea in portAreas)
{
if (portArea.Locode == locode)
{
result[portArea.Code] = portArea.Name;
}
}
return result;
}
#endregion
#region abstract method implementation
public override List<DatabaseEntity> LoadList(IDataReader reader)
{
List<DatabaseEntity> result = new List<DatabaseEntity>();

Binary file not shown.