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 // Preload validation fields
List<ValidationField> vFields = bsmd.database.ValidationRule.ValidationFields; List<ValidationField> vFields = bsmd.database.ValidationRule.ValidationFields;
RuleEngine.RegisterLocodeChecker(Util.GlobalStructures.IsValidLocode); RuleEngine.RegisterLocodeChecker(Util.GlobalStructures.IsValidLocode);
RuleEngine.RegisterPortAreaChecker(LocalizedLookup.PortAreaExists); RuleEngine.RegisterPortAreaChecker(bsmd.database.PortArea.PortAreaExists);
RuleEngine.RegisterNationalityChecker(LocalizedLookup.CheckNationality); RuleEngine.RegisterNationalityChecker(LocalizedLookup.CheckNationality);
// Register expandable Properties // 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); _infoMessage.Elements.Add(info);
} }
portAreas = LocalizedLookup.getPortAreasForLocode(this.Core.PoC); portAreas = PortArea.getPortAreasForLocode(this.Core.PoC);
this.comboBoxPortArea.ItemsSource = portAreas; this.comboBoxPortArea.ItemsSource = portAreas;
this.comboBoxShippingArea.ItemsSource = shippingAreas; this.comboBoxShippingArea.ItemsSource = shippingAreas;

View File

@ -331,12 +331,15 @@
<Compile Include="Controls\ValueMappingsControl.xaml.cs"> <Compile Include="Controls\ValueMappingsControl.xaml.cs">
<DependentUpon>ValueMappingsControl.xaml</DependentUpon> <DependentUpon>ValueMappingsControl.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Controls\HazardMaterialControl.xaml.cs"> <Compile Include="Controls\HazardMaterialControl.xaml.cs">
<DependentUpon>HazardMaterialControl.xaml</DependentUpon> <DependentUpon>HazardMaterialControl.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Controls\WASExemptionsControl.xaml.cs"> <Compile Include="Controls\PortAreaControl.xaml.cs">
<DependentUpon>WASExemptionsControl.xaml</DependentUpon> <DependentUpon>PortAreaControl.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Controls\WASExemptionsControl.xaml.cs">
<DependentUpon>WASExemptionsControl.xaml</DependentUpon>
</Compile>
<Compile Include="EditControls\ChangePasswordDialog.xaml.cs"> <Compile Include="EditControls\ChangePasswordDialog.xaml.cs">
<DependentUpon>ChangePasswordDialog.xaml</DependentUpon> <DependentUpon>ChangePasswordDialog.xaml</DependentUpon>
</Compile> </Compile>
@ -656,14 +659,18 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Controls\HazardMaterialControl.xaml"> <Page Include="Controls\HazardMaterialControl.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Controls\WASExemptionsControl.xaml"> <Page Include="Controls\PortAreaControl.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Controls\WASExemptionsControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="ControlTemplates.xaml"> <Page Include="ControlTemplates.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
@ -1260,4 +1267,4 @@
<Target Name="AfterBuild"> <Target Name="AfterBuild">
</Target> </Target>
--> -->
</Project> </Project>

View File

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

View File

@ -1139,7 +1139,7 @@ namespace ENI2.Excel
info.FumigatedBulkCargoBool = reader.ReadCellAsBool("port message", "C20"); info.FumigatedBulkCargoBool = reader.ReadCellAsBool("port message", "C20");
info.DeplacementSummerDraught_TNE = reader.ReadCellAsDecimal("port message", "C21"); info.DeplacementSummerDraught_TNE = reader.ReadCellAsDecimal("port message", "C21");
string portArea = reader.ReadCellAsText("port message", "C22")?.Trim().ToUpper(); 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; info.PortArea = portArea;
else else
info.PortArea = ""; info.PortArea = "";

View File

@ -504,6 +504,79 @@ namespace ENI2.Excel
#endregion #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) private static string Truncate(string value, int maxLength)
{ {
if (value == null) if (value == null)

View File

@ -956,7 +956,7 @@ namespace ENI2.Excel
ExcelUtil.ScanMessage(info, reader); ExcelUtil.ScanMessage(info, reader);
string portArea = reader.ReadText("INFO.PortArea")?.ToUpper(); 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; info.PortArea = portArea;
} }
@ -3003,4 +3003,4 @@ namespace ENI2.Excel
#endregion "Semi-Manual" import functions (may open interactive dialog) #endregion "Semi-Manual" import functions (may open interactive dialog)
} }
} }

View File

@ -15,8 +15,7 @@ namespace ENI2
{ {
private static readonly SQLiteConnection _con; private static readonly SQLiteConnection _con;
private const string _locode_DB_NAME = "db.sqlite"; private const string _locode_DB_NAME = "db.sqlite";
private static Dictionary<string, string> _nationalities = null; private static Dictionary<string, string> _nationalities = null;
private static Dictionary<string, List<PortAreaInfo>> _portAreaInfos = null;
static LocalizedLookup() static LocalizedLookup()
{ {
@ -41,37 +40,7 @@ namespace ENI2
} }
reader.Close(); reader.Close();
return result; 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) public static bool CheckNationality(string nationality)
{ {
@ -297,44 +266,6 @@ namespace ENI2
} }
reader.Close(); reader.Close();
return result; 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

@ -103,12 +103,17 @@
<Image Source="Resources/garbage.png" /> <Image Source="Resources/garbage.png" />
</MenuItem.Icon> </MenuItem.Icon>
</MenuItem> </MenuItem>
<MenuItem x:Name="menuItemHazardMaterials" Header="Hazard materials" Click="radioButton_Click"> <MenuItem x:Name="menuItemHazardMaterials" Header="Hazard materials" Click="radioButton_Click">
<MenuItem.Icon> <MenuItem.Icon>
<Image Source="Resources/sign_warning.png" /> <Image Source="Resources/sign_warning.png" />
</MenuItem.Icon> </MenuItem.Icon>
</MenuItem> </MenuItem>
</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="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" /> <MenuItem x:Name="menuItemValueMappings" Header="{x:Static p:Resources.textExcelValueMappings}" Click="radioButton_Click" Visibility="Hidden" />
<MenuItem x:Name="menuItemEasyPeasy" Header="{x:Static p:Resources.textEasyPeasy}" Click="radioButton_Click" Visibility="Hidden" /> <MenuItem x:Name="menuItemEasyPeasy" Header="{x:Static p:Resources.textEasyPeasy}" Click="radioButton_Click" Visibility="Hidden" />

View File

@ -42,6 +42,7 @@ namespace ENI2
private EasyPeasyControl easyPeasyControl; private EasyPeasyControl easyPeasyControl;
private WASExemptionsControl wasExemptionsControl; private WASExemptionsControl wasExemptionsControl;
private HazardMaterialControl hazardMaterialControl; private HazardMaterialControl hazardMaterialControl;
private PortAreaControl portAreaControl;
private bool dbConnected; private bool dbConnected;
private readonly ScaleTransform _transform = new ScaleTransform(1.0, 1.0); private readonly ScaleTransform _transform = new ScaleTransform(1.0, 1.0);
@ -351,7 +352,15 @@ namespace ENI2
} }
this.rootContainer.Children.Add(this.hazardMaterialControl); 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) private void buttonCompareSheets_Click(object sender, RoutedEventArgs ev)
{ {

View File

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

View File

@ -30,7 +30,6 @@ namespace bsmd.database
private static DBManager _instance; private static DBManager _instance;
private static readonly ILog _log = LogManager.GetLogger(typeof(DBManager)); private static readonly ILog _log = LogManager.GetLogger(typeof(DBManager));
private static Dictionary<Guid, ReportingParty> allReportingParties; private static Dictionary<Guid, ReportingParty> allReportingParties;
private static Dictionary<string, PortArea> allPortAreas;
private readonly object _lock = new object(); private readonly object _lock = new object();
private bool _closeConnectionAfterUse = false; private bool _closeConnectionAfterUse = false;
private readonly List<string> truncatedFieldCollection = new List<string>(); private readonly List<string> truncatedFieldCollection = new List<string>();
@ -93,6 +92,7 @@ namespace bsmd.database
_con = new SqlConnection(dbConnectionString); _con = new SqlConnection(dbConnectionString);
_con.Open(); _con.Open();
this.ConnectionString = dbConnectionString; this.ConnectionString = dbConnectionString;
DBManagerAsync.ConnectionString = dbConnectionString;
return true; return true;
} }
catch (Exception ex) catch (Exception ex)
@ -109,6 +109,7 @@ namespace bsmd.database
_con = new SqlConnection(dbConnectionString); _con = new SqlConnection(dbConnectionString);
await _con.OpenAsync(); await _con.OpenAsync();
this.ConnectionString = dbConnectionString; this.ConnectionString = dbConnectionString;
DBManagerAsync.ConnectionString = dbConnectionString;
return true; return true;
} }
catch(Exception ex) catch(Exception ex)
@ -440,19 +441,7 @@ namespace bsmd.database
public Dictionary<string, PortArea> GetPortAreaDict() public Dictionary<string, PortArea> GetPortAreaDict()
{ {
if(DBManager.allPortAreas == null) return DBManagerAsync.GetPortAreaDict();
{
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;
} }
public DatabaseEntity GetMessageById(Guid id) public DatabaseEntity GetMessageById(Guid id)
@ -629,8 +618,8 @@ namespace bsmd.database
this.Delete(messageCore); this.Delete(messageCore);
} }
public void Save(DatabaseEntity entity) public void Save(DatabaseEntity entity)
{ {
List<string> truncatedFields = new List<string>(); List<string> truncatedFields = new List<string>();
List<string> fieldNames = new List<string>(); List<string> fieldNames = new List<string>();
entity.TruncateFields(truncatedFields, fieldNames); entity.TruncateFields(truncatedFields, fieldNames);
@ -646,28 +635,28 @@ namespace bsmd.database
entity.PrepareSave(cmd); entity.PrepareSave(cmd);
int queryResult = this.PerformNonQuery(cmd); int queryResult = this.PerformNonQuery(cmd);
this.LogNonQueryResult(cmd.CommandText, queryResult); this.LogNonQueryResult(cmd.CommandText, queryResult);
this.CreateEntityHistoryEntry(entity); this.CreateEntityHistoryEntry(entity);
if (entity is PortArea) if (entity is PortArea)
DBManager.allPortAreas = null; DBManagerAsync.InvalidatePortAreaCache();
if (this._closeConnectionAfterUse) this.Disconnect();
}
public void Delete(DatabaseEntity entity) if (this._closeConnectionAfterUse) this.Disconnect();
{ }
public void Delete(DatabaseEntity entity)
{
if (!entity.IsNew) if (!entity.IsNew)
{ {
using (SqlCommand cmd = new SqlCommand()) using (SqlCommand cmd = new SqlCommand())
{ {
entity.PrepareDelete(cmd); entity.PrepareDelete(cmd);
int queryResult = this.PerformNonQuery(cmd); int queryResult = this.PerformNonQuery(cmd);
this.LogNonQueryResult(cmd.CommandText, queryResult); this.LogNonQueryResult(cmd.CommandText, queryResult);
} }
} }
if (entity is PortArea) if (entity is PortArea)
DBManager.allPortAreas = null; DBManagerAsync.InvalidatePortAreaCache();
if (this._closeConnectionAfterUse) this.Disconnect(); if (this._closeConnectionAfterUse) this.Disconnect();
} }
public void DeleteMessageErrors(Message message) public void DeleteMessageErrors(Message message)
{ {

View File

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

View File

@ -232,35 +232,6 @@ namespace bsmd.database
#endregion #endregion
} }
#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,10 +1,10 @@
// Copyright (c) 2015-2017 schick Informatik // Copyright (c) 2015-.. schick Informatik
// Description: // Description: DB entity for port areas
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data; using System.Data;
using System.Data.SqlClient; using System.Data.SqlClient;
namespace bsmd.database namespace bsmd.database
{ {
@ -52,7 +52,41 @@ namespace bsmd.database
#endregion #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 #region abstract method implementation
public override List<DatabaseEntity> LoadList(IDataReader reader) public override List<DatabaseEntity> LoadList(IDataReader reader)
{ {
List<DatabaseEntity> result = new List<DatabaseEntity>(); List<DatabaseEntity> result = new List<DatabaseEntity>();
@ -90,34 +124,34 @@ namespace bsmd.database
cmd.CommandText = query; cmd.CommandText = query;
} }
public override void PrepareSave(IDbCommand cmd) public override void PrepareSave(IDbCommand cmd)
{ {
SqlCommand scmd = cmd as SqlCommand; SqlCommand scmd = cmd as SqlCommand;
scmd.Parameters.AddWithNullableValue("@COUNTRY", this.Country); scmd.Parameters.AddWithNullableValue("@COUNTRY", this.Country);
scmd.Parameters.AddWithNullableValue("@LOCODE", this.Locode); scmd.Parameters.AddWithNullableValue("@LOCODE", this.Locode);
scmd.Parameters.AddWithNullableValue("@PORT", this.Port); scmd.Parameters.AddWithNullableValue("@PORT", this.Port);
scmd.Parameters.AddWithNullableValue("@CODE", this.Code); scmd.Parameters.AddWithNullableValue("@CODE", this.Code);
scmd.Parameters.AddWithNullableValue("@NAME", this.Name); scmd.Parameters.AddWithNullableValue("@NAME", this.Name);
scmd.Parameters.AddWithNullableValue("@AGENCY", this.Agency); scmd.Parameters.AddWithNullableValue("@AGENCY", this.Agency);
scmd.Parameters.AddWithNullableValue("@BERTH", this.Berth); scmd.Parameters.AddWithNullableValue("@BERTH", this.Berth);
scmd.Parameters.AddWithNullableValue("@SHIPS", this.Ships); scmd.Parameters.AddWithNullableValue("@SHIPS", this.Ships);
scmd.Parameters.AddWithNullableValue("@REMARKS", this.Remarks); scmd.Parameters.AddWithNullableValue("@REMARKS", this.Remarks);
if (this.IsNew) if (this.IsNew)
{ {
this.CreateId(); this.CreateId();
scmd.Parameters.AddWithValue("@ID", this.Id); scmd.Parameters.AddWithValue("@ID", this.Id);
scmd.CommandText = string.Format("INSERT INTO {0} (Id, Country, Locode, Port, Code, Name, Agency, Berth, Ships, Remarks) " + scmd.CommandText = string.Format("INSERT INTO {0} (Id, Country, Locode, Port, Code, Name, Agency, Berth, Ships, Remarks) " +
"VALUES (@ID, @COUNTRY, @LOCODE, @PORT, @CODE, @NAME, @AGENCY, @BERTH, @SHIPS, @REMARKS)", this.Tablename); "VALUES (@ID, @COUNTRY, @LOCODE, @PORT, @CODE, @NAME, @AGENCY, @BERTH, @SHIPS, @REMARKS)", this.Tablename);
} }
else else
{ {
scmd.Parameters.AddWithValue("@ID", this.Id); scmd.Parameters.AddWithValue("@ID", this.Id);
scmd.CommandText = string.Format("UPDATE {0} SET Country = @COUNTRY, Locode = @LOCODE, Port = @PORT, Code = @CODE, Name = @NAME, " + scmd.CommandText = string.Format("UPDATE {0} SET Country = @COUNTRY, Locode = @LOCODE, Port = @PORT, Code = @CODE, Name = @NAME, " +
"Agency = @AGENCY, Berth = @BERTH, Ships = @SHIPS, Remarks = @REMARKS WHERE Id = @ID", this.Tablename); "Agency = @AGENCY, Berth = @BERTH, Ships = @SHIPS, Remarks = @REMARKS WHERE Id = @ID", this.Tablename);
} }
} }
#endregion #endregion

Binary file not shown.