Sicherung Zwischenstand

This commit is contained in:
Daniel Schick 2017-06-10 07:19:05 +00:00
parent 14c5daff20
commit 130d8c608e
37 changed files with 409 additions and 185 deletions

View File

@ -20,13 +20,14 @@
<value>True</value> <value>True</value>
</setting> </setting>
<setting name="LockingServerAddress" serializeAs="String"> <setting name="LockingServerAddress" serializeAs="String">
<value>http://heupferd/bsmd.LockingService/LockingService.svc</value> <!--value>http://heupferd/bsmd.LockingService/LockingService.svc</value-->
<value>http://192.168.2.4/LockingService/LockingService.svc</value>
</setting> </setting>
<setting name="RequestTimeout" serializeAs="String"> <setting name="RequestTimeout" serializeAs="String">
<value>60</value> <value>60</value>
</setting> </setting>
<setting name="ConnectionString" serializeAs="String"> <setting name="ConnectionString" serializeAs="String">
<value>Data Source=192.168.2.12;Initial Catalog=nsw;Uid=dfuser;Pwd=dfpasswd;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False</value> <value>Data Source=(localdb)\Projects;Initial Catalog=nsw;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False</value>
</setting> </setting>
</ENI2.Properties.Settings> </ENI2.Properties.Settings>
</applicationSettings> </applicationSettings>

View File

@ -6,6 +6,7 @@
xmlns:p="clr-namespace:ENI2.Properties" xmlns:p="clr-namespace:ENI2.Properties"
StartupUri="MainWindow.xaml"> StartupUri="MainWindow.xaml">
<Application.Resources> <Application.Resources>
<ContextMenu x:Key="ClearContextMenu" x:Shared="true"> <ContextMenu x:Key="ClearContextMenu" x:Shared="true">
<MenuItem Header="{x:Static p:Resources.textClear}" IsCheckable="False" Command="local:CustomCommands.Clear" > <MenuItem Header="{x:Static p:Resources.textClear}" IsCheckable="False" Command="local:CustomCommands.Clear" >
<MenuItem.Icon> <MenuItem.Icon>
@ -13,5 +14,14 @@
</MenuItem.Icon> </MenuItem.Icon>
</MenuItem> </MenuItem>
</ContextMenu> </ContextMenu>
<Style TargetType="DataGridRow">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="LightYellow" />
</Trigger>
</Style.Triggers>
</Style>
</Application.Resources> </Application.Resources>
</Application> </Application>

View File

@ -51,11 +51,12 @@ namespace ENI2.Controls
public event EventHandler TabClosing; public event EventHandler TabClosing;
public void SetHeaderText(string headerText) public void SetHeaderText(string headerText, bool lockedTab)
{ {
// Container for header controls // Container for header controls
var dockPanel = new DockPanel(); var dockPanel = new DockPanel();
var header = new TextBlock { Text = headerText }; var header = new TextBlock { Text = headerText };
header.Background = lockedTab ? Brushes.LightGreen : Brushes.Orange;
dockPanel.Children.Add(header); dockPanel.Children.Add(header);
// Close button to remove the tab // Close button to remove the tab

View File

@ -14,11 +14,14 @@ namespace ENI2.Controls
/// </summary> /// </summary>
[TemplatePart(Name = "buttonOK", Type = typeof(Button))] [TemplatePart(Name = "buttonOK", Type = typeof(Button))]
[TemplatePart(Name = "buttonCancel", Type = typeof(Button))] [TemplatePart(Name = "buttonCancel", Type = typeof(Button))]
[TemplatePart(Name = "buttonAdd", Type = typeof(Button))]
public class EditWindowBase : Window public class EditWindowBase : Window
{ {
public event Action OKClicked; public event Action OKClicked;
public event Action CancelClicked; public event Action CancelClicked;
public event Action AddClicked;
protected bool shouldCancel; protected bool shouldCancel;
static EditWindowBase() static EditWindowBase()
@ -32,14 +35,22 @@ namespace ENI2.Controls
{ {
var okButton = (Button)Template.FindName("buttonOK", this); var okButton = (Button)Template.FindName("buttonOK", this);
var cancelButton = (Button)Template.FindName("buttonCancel", this); var cancelButton = (Button)Template.FindName("buttonCancel", this);
var addButton = (Button)Template.FindName("buttonAdd", this);
okButton.Click += (s, e) => { if (IsModal) DialogResult = true; else this.Close(); OKClicked?.Invoke(); }; okButton.Click += (s, e) => { if (IsModal) DialogResult = true; else this.Close(); OKClicked?.Invoke(); };
cancelButton.Click += (s, e) => { if (IsModal) DialogResult = false; else this.Close(); CancelClicked?.Invoke(); }; cancelButton.Click += (s, e) => { if (IsModal) DialogResult = false; else this.Close(); CancelClicked?.Invoke(); };
addButton.Click += (s, e) => { AddClicked?.Invoke(); };
}; };
this.IsModal = true; // default this.IsModal = true; // default
} }
public bool IsModal { get; set; } public bool IsModal { get; set; }
public bool AddVisible
{
get { var addButton = (Button)Template.FindName("buttonAdd", this); return addButton.Visibility == Visibility.Visible; }
set { var addButton = (Button)Template.FindName("buttonAdd", this); addButton.Visibility = value ? Visibility.Visible : Visibility.Hidden; }
}
private void Window_Closing(object sender, CancelEventArgs e) private void Window_Closing(object sender, CancelEventArgs e)
{ {
if (this.shouldCancel) e.Cancel = true; if (this.shouldCancel) e.Cancel = true;

View File

@ -14,10 +14,12 @@
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<xctk:WatermarkComboBox Grid.Column="0" x:Name="comboBoxLocode" Margin="2" IsEditable="True" Watermark="{x:Static p:Resources.textTypeLocode}" VerticalContentAlignment="Center" <xctk:WatermarkComboBox Grid.Column="0" x:Name="comboBoxLocode" Margin="2" IsEditable="True" Watermark="{x:Static p:Resources.textTypeLocode}"
TextBoxBase.TextChanged="ComboBox_TextChanged" SelectionChanged="comboBoxLocode_SelectionChanged"/> <!-- ItemsSource="{Binding LocodeList, Mode=TwoWay}" VerticalContentAlignment="Center"
SelectedItem="{Binding LocodeValue}" /> --> TextBoxBase.TextChanged="ComboBox_TextChanged"
<!--, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:LocodeControl}}--> SelectionChanged="comboBoxLocode_SelectionChanged" PreviewKeyDown="comboBoxLocode_PreviewKeyDown"/>
<Image Name="imageLocodeState" Grid.Column="1" Source="../Resources/bullet_ball_grey.png" /> <Image Name="imageLocodeState" Grid.Column="1" Source="../Resources/bullet_ball_grey.png" />
</Grid> </Grid>
</UserControl> </UserControl>

View File

@ -95,7 +95,7 @@ namespace ENI2.Controls
private void ComboBox_TextChanged(object sender, RoutedEventArgs e) private void ComboBox_TextChanged(object sender, RoutedEventArgs e)
{ {
bool locodeFound = false; bool locodeFound = false;
this.comboBoxLocode.ItemsSource = null;
if (this._comboSelect) if (this._comboSelect)
{ {
@ -105,6 +105,7 @@ namespace ENI2.Controls
else else
{ {
this.comboBoxLocode.ItemsSource = null;
if (this.comboBoxLocode.Text.Length > 4) if (this.comboBoxLocode.Text.Length > 4)
{ {
@ -131,14 +132,18 @@ namespace ENI2.Controls
{ {
// assume this is a harbour name typed out.. // assume this is a harbour name typed out..
List<LocodeDB.LocodeEntry> locodeEntries = LocodeDB.AllLocodesForCityNameAsEntries("%" + this.comboBoxLocode.Text + "%"); List<LocodeDB.LocodeEntry> locodeEntries = LocodeDB.AllLocodesForCityNameAsEntries("%" + this.comboBoxLocode.Text + "%");
locodeEntries.Sort();
foreach (LocodeDB.LocodeEntry entry in locodeEntries) foreach (LocodeDB.LocodeEntry entry in locodeEntries)
this.LocodeList.Add(string.Format("{0} - {1}", entry.Locode, entry.Name)); this.LocodeList.Add(string.Format("{0} - {1}", entry.Locode, entry.Name));
this.comboBoxLocode.ItemsSource = this.LocodeList;
if (this.LocodeList.Count == 1) if (this.LocodeList.Count == 1)
{ {
this.comboBoxLocode.SelectedItem = this.LocodeList[0]; this.comboBoxLocode.SelectedItem = this.LocodeList[0];
this.SetLocodeStateImage(this.imageLocodeState, LocodeState.OK); this.SetLocodeStateImage(this.imageLocodeState, LocodeState.OK);
this.LocodeValue = this.LocodeList[0]; this.LocodeValue = this.LocodeList[0].Substring(0,5);
} }
else if (this.LocodeList.Count == 0) else if (this.LocodeList.Count == 0)
{ {
@ -148,13 +153,12 @@ namespace ENI2.Controls
{ {
this.SetLocodeStateImage(this.imageLocodeState, LocodeState.AMBIGUOUS); this.SetLocodeStateImage(this.imageLocodeState, LocodeState.AMBIGUOUS);
} }
this.comboBoxLocode.ItemsSource = this.LocodeList;
} }
} }
} }
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("LocodeList")); this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("LocodeList"));
} }
private void comboBoxLocode_SelectionChanged(object sender, SelectionChangedEventArgs e) private void comboBoxLocode_SelectionChanged(object sender, SelectionChangedEventArgs e)
@ -201,5 +205,13 @@ namespace ENI2.Controls
#endregion #endregion
private void comboBoxLocode_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
if((e.Key == System.Windows.Input.Key.Down) && !this.comboBoxLocode.IsDropDownOpen)
{
this.comboBoxLocode.IsDropDownOpen = true;
e.Handled = true;
}
}
} }
} }

View File

@ -57,11 +57,6 @@ namespace ENI2
/// </summary> /// </summary>
public event Action RequestReload; public event Action RequestReload;
/// <summary>
/// Mit diesem Event wird der Wunsch nach einem Lock zum Ausdruck gebracht ;-)
/// </summary>
public event Action<bool> RequestLock;
/// <summary> /// <summary>
/// Eine in der Detailansicht enthaltene Meldeklasse hat sich geändert /// Eine in der Detailansicht enthaltene Meldeklasse hat sich geändert
/// </summary> /// </summary>
@ -88,6 +83,8 @@ namespace ENI2
public Guid UserId { get; set; } // TODO: Ersetzen mit der User-Entity public Guid UserId { get; set; } // TODO: Ersetzen mit der User-Entity
public bool LockedByOtherUser { get; set; }
#endregion #endregion
#region public methods #region public methods
@ -123,31 +120,6 @@ namespace ENI2
this.RequestReload?.Invoke(); this.RequestReload?.Invoke();
} }
protected virtual void OnRequestLock(bool shouldLock)
{
this.RequestLock?.Invoke(shouldLock);
}
protected void SetLocodeStateImage(Image stateImage, LocodeState state)
{
switch(state)
{
case LocodeState.AMBIGUOUS:
stateImage.Source = new BitmapImage(new Uri("pack://application:,,,/Resources/bullet_ball_yellow.png"));
break;
case LocodeState.INVALID:
stateImage.Source = new BitmapImage(new Uri("pack://application:,,,/Resources/bullet_ball_red.png"));
break;
case LocodeState.OK:
stateImage.Source = new BitmapImage(new Uri("pack://application:,,,/Resources/bullet_ball_green.png"));
break;
case LocodeState.UNKNOWN:
default:
stateImage.Source = new BitmapImage(new Uri("pack://application:,,,/Resources/bullet_ball_grey.png"));
break;
}
}
#region event handling for control content changes (signal dirty etc) #region event handling for control content changes (signal dirty etc)
protected void RegisterTextboxChange(TextBox textBox, Message.NotificationClass notificationClass) protected void RegisterTextboxChange(TextBox textBox, Message.NotificationClass notificationClass)

View File

@ -11,6 +11,7 @@ using bsmd.database;
using ENI2.DetailViewControls; using ENI2.DetailViewControls;
using ENI2.LockingServiceReference; using ENI2.LockingServiceReference;
using System.Windows; using System.Windows;
using System.Windows.Data;
namespace ENI2 namespace ENI2
{ {
@ -27,6 +28,7 @@ namespace ENI2
private List<Message> _messages; private List<Message> _messages;
private Dictionary<Type, DetailBaseControl> controlCache = new Dictionary<Type, DetailBaseControl>(); private Dictionary<Type, DetailBaseControl> controlCache = new Dictionary<Type, DetailBaseControl>();
private Guid userId = Guid.NewGuid(); // remove THIS!! private Guid userId = Guid.NewGuid(); // remove THIS!!
private object messageListLock = new object();
#endregion #endregion
@ -34,6 +36,7 @@ namespace ENI2
public MessageCore Core { get { return this._core; } } public MessageCore Core { get { return this._core; } }
public bool LockedByOtherUser { get; set; }
#endregion #endregion
@ -67,6 +70,7 @@ namespace ENI2
this.listBoxMessages.ItemsSource = this._listBoxList; this.listBoxMessages.ItemsSource = this._listBoxList;
_messages = DBManager.Instance.GetMessagesForCore(_core, DBManager.MessageLoad.ALL); _messages = DBManager.Instance.GetMessagesForCore(_core, DBManager.MessageLoad.ALL);
BindingOperations.EnableCollectionSynchronization(_messages, this.messageListLock);
Dispatcher.BeginInvoke((Action)(() => this.listBoxMessages.SelectedIndex = 0)); Dispatcher.BeginInvoke((Action)(() => this.listBoxMessages.SelectedIndex = 0));
} }
@ -86,6 +90,7 @@ namespace ENI2
#endregion #endregion
#region event handler
private void listBoxMessages_SelectionChanged(object sender, SelectionChangedEventArgs e) private void listBoxMessages_SelectionChanged(object sender, SelectionChangedEventArgs e)
{ {
@ -98,6 +103,7 @@ namespace ENI2
DetailBaseControl detailControl = (DetailBaseControl)Activator.CreateInstance(mg.MessageGroupControlType); DetailBaseControl detailControl = (DetailBaseControl)Activator.CreateInstance(mg.MessageGroupControlType);
detailControl.Core = _core; detailControl.Core = _core;
detailControl.Messages = _messages; detailControl.Messages = _messages;
detailControl.LockedByOtherUser = this.LockedByOtherUser;
detailControl.JumpToListElementRequest += (index) => detailControl.JumpToListElementRequest += (index) =>
{ {
@ -108,10 +114,11 @@ namespace ENI2
}; };
detailControl.RequestReload += DetailControl_RequestReload; detailControl.RequestReload += DetailControl_RequestReload;
detailControl.RequestLock += DetailControl_RequestLock;
detailControl.NotificationClassChanged += DetailControl_NotificationClassChanged; detailControl.NotificationClassChanged += DetailControl_NotificationClassChanged;
detailControl.Initialize(); detailControl.Initialize();
detailControl.IsEnabled = !this.LockedByOtherUser;
controlCache.Add(mg.MessageGroupControlType, detailControl); controlCache.Add(mg.MessageGroupControlType, detailControl);
this.buttonSave.Visibility = Visibility.Hidden; this.buttonSave.Visibility = Visibility.Hidden;
} }
@ -193,8 +200,8 @@ namespace ENI2
{ {
try try
{ {
string lockResult = App.LockingServiceClient.Lock(this.Core.Id.Value, this.userId.ToString()); Guid lockedUserId = App.LockingServiceClient.Lock(this.Core.Id.Value, this.userId);
if (lockResult == "") if (lockedUserId == Guid.Empty)
{ {
// lock successful // lock successful
this.Core.Locked = true; this.Core.Locked = true;
@ -214,7 +221,7 @@ namespace ENI2
} }
else else
{ {
App.LockingServiceClient.Unlock(this.Core.Id.Value, this.userId.ToString()); App.LockingServiceClient.Unlock(this.Core.Id.Value, this.userId);
this.Core.Locked = false; this.Core.Locked = false;
} }
} }
@ -233,5 +240,8 @@ namespace ENI2
// return to "new" overview // return to "new" overview
Dispatcher.BeginInvoke((Action)(() => this.listBoxMessages_SelectionChanged(this, null))); Dispatcher.BeginInvoke((Action)(() => this.listBoxMessages_SelectionChanged(this, null)));
} }
#endregion
} }
} }

View File

@ -73,13 +73,12 @@
<Label HorizontalContentAlignment="Right" Grid.Row="4" Grid.Column="3" Content="{x:Static p:Resources.textCreated}" Margin="0,0,10,0" /> <Label HorizontalContentAlignment="Right" Grid.Row="4" Grid.Column="3" Content="{x:Static p:Resources.textCreated}" Margin="0,0,10,0" />
<Label Name="labelCreated" Grid.Column="4" Grid.Row="4" Margin="2, 0, 0, 0" /> <Label Name="labelCreated" Grid.Column="4" Grid.Row="4" Margin="2, 0, 0, 0" />
<TextBox Name="textBoxTicketNo" Grid.Column="1" Grid.Row="4" Grid.ColumnSpan="2" Text="{Binding TicketNo}" Margin="2" /> <TextBox Name="textBoxTicketNo" Grid.Column="1" Grid.Row="4" Grid.ColumnSpan="2" Text="{Binding TicketNo}" Margin="2" />
<!-- Command buttons -->
<Button Name="buttonLock" Grid.Column="0" Grid.Row="6" Margin="2" Click="buttonLock_Click" BorderThickness="0" Background="Transparent"> <StackPanel Orientation="Horizontal" Grid.Column="0" Grid.Row="6" Visibility="Hidden" Name="stackPanelLock">
<StackPanel Orientation="Horizontal"> <Image Source="../Resources/lock.png" Margin="0,0,5,0" Height="24" />
<Image Source="../Resources/lock_open.png" Margin="0,0,5,0" Height="24" /> <TextBlock Name="textBlockLockUserName" VerticalAlignment="Center" />
<TextBlock Text="{x:Static p:Resources.textLock}" VerticalAlignment="Center" /> </StackPanel>
</StackPanel>
</Button>
<Button IsEnabled="False" Name="buttonStorno" Grid.Column="1" Grid.Row="6" Margin="2" Click="buttonStorno_Click" Content="{x:Static p:Resources.textCancelDeclaration}"/> <Button IsEnabled="False" Name="buttonStorno" Grid.Column="1" Grid.Row="6" Margin="2" Click="buttonStorno_Click" Content="{x:Static p:Resources.textCancelDeclaration}"/>
<Button IsEnabled="False" Name="buttonCopy" Grid.Column="2" Grid.Row="6" Margin="2" Click="buttonCopy_Click" Content="{x:Static p:Resources.textCopyData}"/> <Button IsEnabled="False" Name="buttonCopy" Grid.Column="2" Grid.Row="6" Margin="2" Click="buttonCopy_Click" Content="{x:Static p:Resources.textCopyData}"/>
<Button IsEnabled="False" Name="buttonSendPDF" Grid.Column="3" Grid.Row="6" Margin="2" Click="buttonSendPDF_Click" Content="{x:Static p:Resources.textCreatePDF}"/> <Button IsEnabled="False" Name="buttonSendPDF" Grid.Column="3" Grid.Row="6" Margin="2" Click="buttonSendPDF_Click" Content="{x:Static p:Resources.textCreatePDF}"/>

View File

@ -11,6 +11,7 @@ using System.Timers;
using bsmd.database; using bsmd.database;
using ENI2.EditControls; using ENI2.EditControls;
using System.Windows.Media.Imaging;
namespace ENI2.DetailViewControls namespace ENI2.DetailViewControls
{ {
@ -188,6 +189,17 @@ namespace ENI2.DetailViewControls
// kann das eigentlich passieren??! // kann das eigentlich passieren??!
} }
#region Context-Menu Meldeklassen
this.dataGridMessages.ContextMenu = new ContextMenu();
MenuItem sendItem = new MenuItem();
sendItem.Header = Properties.Resources.textSendToNSW;
sendItem.Icon = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/Resources/mail_forward.png")) };
sendItem.Click += new RoutedEventHandler(this.contextSendMessage);
this.dataGridMessages.ContextMenu.Items.Add(sendItem);
#endregion
#region init ATA #region init ATA
// ganz hakelig ich weiß dafür kapiert das gleich jeder // ganz hakelig ich weiß dafür kapiert das gleich jeder
@ -322,6 +334,11 @@ namespace ENI2.DetailViewControls
#region Command button event handler #region Command button event handler
private void contextSendMessage(object sender, RoutedEventArgs e)
{
MessageBox.Show("not yet..");
}
private void buttonStorno_Click(object sender, RoutedEventArgs e) private void buttonStorno_Click(object sender, RoutedEventArgs e)
{ {
@ -414,18 +431,6 @@ namespace ENI2.DetailViewControls
})); }));
} }
private void buttonLock_Click(object sender, RoutedEventArgs e)
{
this.Dispatcher.BeginInvoke(new Action(() =>
{
bool reqValue = true;
if (this.Core.Locked ?? false) // I locked it already, means unlock now
reqValue = false;
this.OnRequestLock(reqValue);
}));
}
private void buttonInfoCore_Click(object sender, RoutedEventArgs e) private void buttonInfoCore_Click(object sender, RoutedEventArgs e)
{ {
SimplePropertyViewDialog spvd = new SimplePropertyViewDialog(); SimplePropertyViewDialog spvd = new SimplePropertyViewDialog();

View File

@ -116,12 +116,20 @@ namespace ENI2.DetailViewControls
private void DataGridCallPurposes_CreateRequested() private void DataGridCallPurposes_CreateRequested()
{ {
CallPurpose cp = new CallPurpose();
EditCallPurposeDialog ecpd = new EditCallPurposeDialog(); EditCallPurposeDialog ecpd = new EditCallPurposeDialog();
ecpd.CallPurpose = cp; ecpd.AddClicked += () =>
{
ecpd.CopyValuesToEntity();
if (!_noa_nod.CallPurposes.Contains(ecpd.CallPurpose))
_noa_nod.CallPurposes.Add(ecpd.CallPurpose);
this.dataGridCallPurposes.Items.Refresh();
ecpd.CallPurpose = new CallPurpose();
};
ecpd.CallPurpose = new CallPurpose();
if(ecpd.ShowDialog() ?? false) if(ecpd.ShowDialog() ?? false)
{ {
_noa_nod.CallPurposes.Add(cp); if(!_noa_nod.CallPurposes.Contains(ecpd.CallPurpose))
_noa_nod.CallPurposes.Add(ecpd.CallPurpose);
this.dataGridCallPurposes.Items.Refresh(); this.dataGridCallPurposes.Items.Refresh();
} }
} }
@ -135,8 +143,18 @@ namespace ENI2.DetailViewControls
{ {
EditCallPurposeDialog ecpd = new EditCallPurposeDialog(); EditCallPurposeDialog ecpd = new EditCallPurposeDialog();
ecpd.CallPurpose = obj as CallPurpose; ecpd.CallPurpose = obj as CallPurpose;
if(ecpd.ShowDialog() ?? false) ecpd.AddClicked += () =>
{ {
ecpd.CopyValuesToEntity();
if (!_noa_nod.CallPurposes.Contains(ecpd.CallPurpose))
_noa_nod.CallPurposes.Add(ecpd.CallPurpose);
this.dataGridCallPurposes.Items.Refresh();
ecpd.CallPurpose = new CallPurpose();
};
if (ecpd.ShowDialog() ?? false)
{
if (!_noa_nod.CallPurposes.Contains(ecpd.CallPurpose))
_noa_nod.CallPurposes.Add(ecpd.CallPurpose);
this.dataGridCallPurposes.Items.Refresh(); this.dataGridCallPurposes.Items.Refresh();
// signal up // signal up
this.SublistElementChanged(Message.NotificationClass.NOA_NOD); this.SublistElementChanged(Message.NotificationClass.NOA_NOD);

View File

@ -2,20 +2,9 @@
// Description: Detailansicht Gruppe Port Notification // Description: Detailansicht Gruppe Port Notification
// //
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ENI2.EditControls; using ENI2.EditControls;

View File

@ -418,6 +418,7 @@
<None Include="Resources\delete2.png" /> <None Include="Resources\delete2.png" />
<None Include="Resources\mail_new.png" /> <None Include="Resources\mail_new.png" />
<Resource Include="Resources\document_view.png" /> <Resource Include="Resources\document_view.png" />
<Resource Include="Resources\mail_forward.png" />
<Content Include="x64\SQLite.Interop.dll"> <Content Include="x64\SQLite.Interop.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content> </Content>

View File

@ -1,20 +1,9 @@
// Copyright (c) 2017 schick Informatik // Copyright (c) 2017 schick Informatik
// Description: // Description: Bearbeitung von Call Purposes
// //
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using ENI2.Controls; using ENI2.Controls;
using bsmd.database; using bsmd.database;
@ -62,7 +51,6 @@ namespace ENI2.EditControls
InitializeComponent(); InitializeComponent();
Loaded += EditCallPurposeDialog_Loaded; Loaded += EditCallPurposeDialog_Loaded;
} }
public CallPurpose CallPurpose { get; set; } public CallPurpose CallPurpose { get; set; }
@ -82,9 +70,16 @@ namespace ENI2.EditControls
} }
} }
public void CopyValuesToEntity()
{
this.CallPurpose.CallPurposeCode = this.comboBoxCode.SelectedIndex;
this.CallPurpose.CallPurposeDescription = this.textBoxDescription.Text;
}
private void EditCallPurposeDialog_Loaded(object sender, RoutedEventArgs e) private void EditCallPurposeDialog_Loaded(object sender, RoutedEventArgs e)
{ {
this.OKClicked += EditCallPurposeDialog_OKClicked; this.OKClicked += EditCallPurposeDialog_OKClicked;
this.AddVisible = true;
this.comboBoxCode.ItemsSource = this.EdiCodes; this.comboBoxCode.ItemsSource = this.EdiCodes;
if((this.CallPurpose != null) && (this.CallPurpose.CallPurposeCode != 0)) if((this.CallPurpose != null) && (this.CallPurpose.CallPurposeCode != 0))
@ -96,9 +91,7 @@ namespace ENI2.EditControls
private void EditCallPurposeDialog_OKClicked() private void EditCallPurposeDialog_OKClicked()
{ {
// copy selected values back into entity this.CopyValuesToEntity();
this.CallPurpose.CallPurposeCode = this.comboBoxCode.SelectedIndex;
this.CallPurpose.CallPurposeDescription = this.textBoxDescription.Text;
} }
private void comboBoxCode_Selected(object sender, RoutedEventArgs e) private void comboBoxCode_Selected(object sender, RoutedEventArgs e)
@ -106,7 +99,8 @@ namespace ENI2.EditControls
if (this.comboBoxCode.SelectedIndex != this.CallPurpose.CallPurposeCode) if (this.comboBoxCode.SelectedIndex != this.CallPurpose.CallPurposeCode)
{ {
this.textBoxDescription.Text = edifact8025Codes[this.comboBoxCode.SelectedIndex]; this.textBoxDescription.Text = edifact8025Codes[this.comboBoxCode.SelectedIndex];
this.OnOkClicked(); this.textBoxDescription.Focus();
// this.OnOkClicked(); // doch nicht gleich zu
} }
} }
} }

View File

@ -33,8 +33,6 @@
MouseWheelActiveOnFocus="True" MouseWheelActiveOnFocus="True"
FormatString="G" FormatString="G"
Increment="1" Increment="1"
Maximum="9999999"
Minimum="1000000"
DisplayDefaultValueOnEmptyText="False" DisplayDefaultValueOnEmptyText="False"
ButtonSpinnerLocation="Right" ButtonSpinnerLocation="Right"
ParsingNumberStyle="Integer" ParsingNumberStyle="Integer"
@ -48,8 +46,6 @@
MouseWheelActiveOnFocus="True" MouseWheelActiveOnFocus="True"
FormatString="00000000" FormatString="00000000"
Increment="1" Increment="1"
Minimum="1000000"
Maximum="99999999"
DisplayDefaultValueOnEmptyText="False" DisplayDefaultValueOnEmptyText="False"
ButtonSpinnerLocation="Right" ButtonSpinnerLocation="Right"
ParsingNumberStyle="Integer" ParsingNumberStyle="Integer"

View File

@ -15,6 +15,7 @@ using System.Windows.Controls;
using ENI2.Controls; using ENI2.Controls;
using ENI2.EditControls; using ENI2.EditControls;
using System.Threading; using System.Threading;
using log4net;
namespace ENI2 namespace ENI2
{ {
@ -32,8 +33,10 @@ namespace ENI2
private bool efMode = false; private bool efMode = false;
ScaleTransform _transform = new ScaleTransform(1.0, 1.0); ScaleTransform _transform = new ScaleTransform(1.0, 1.0);
private Dictionary<Guid, ClosableTabItem> openTabs = new Dictionary<Guid, ClosableTabItem>(); private Dictionary<Guid, ClosableTabItem> openTabs = new Dictionary<Guid, ClosableTabItem>();
private Dictionary<ClosableTabItem, Guid> lockedCores = new Dictionary<ClosableTabItem, Guid>();
private int failedLogonCount = 0; private int failedLogonCount = 0;
private ReportingParty userEntity = null; private ReportingParty userEntity = null;
private ILog _log = LogManager.GetLogger(typeof(MainWindow));
#endregion #endregion
@ -63,10 +66,30 @@ namespace ENI2
if (!openTabs.ContainsKey(aMessageCore.Id.Value)) if (!openTabs.ContainsKey(aMessageCore.Id.Value))
{ {
ClosableTabItem searchResultItem = new ClosableTabItem(); ClosableTabItem searchResultItem = new ClosableTabItem();
// try to lock the item
Guid lockedUserId = Guid.Empty;
try
{
lockedUserId = App.LockingServiceClient.Lock(aMessageCore.Id.Value, this.userEntity.Id.Value);
if(lockedUserId == Guid.Empty)
{
this.lockedCores[searchResultItem] = aMessageCore.Id.Value;
}
}
catch(Exception ex)
{
// TODO: wenn der Locking Service nicht erreichbar ist sollte das Ganze trotzdem noch irgendwie funktionieren
_log.ErrorFormat("LockingService.Lock: {0}", ex.Message);
}
bool iDidLockIt = (lockedUserId == Guid.Empty);
searchResultItem.TabClosing += SearchResultItem_TabClosing; searchResultItem.TabClosing += SearchResultItem_TabClosing;
DateTime? eta = aMessageCore.IsTransit ? aMessageCore.ETAKielCanal : aMessageCore.ETA; DateTime? eta = aMessageCore.IsTransit ? aMessageCore.ETAKielCanal : aMessageCore.ETA;
searchResultItem.SetHeaderText(string.Format("{0} [{1}-{2}]", aMessageCore.Shipname, aMessageCore.PoC, eta.HasValue ? eta.Value.ToShortDateString() : "")); searchResultItem.SetHeaderText(string.Format("{0} [{1}-{2}]", aMessageCore.Shipname, aMessageCore.PoC, eta.HasValue ? eta.Value.ToShortDateString() : ""),
iDidLockIt);
DetailRootControl drc = new DetailRootControl(aMessageCore); DetailRootControl drc = new DetailRootControl(aMessageCore);
drc.LockedByOtherUser = !iDidLockIt;
searchResultItem.Content = drc; searchResultItem.Content = drc;
this.mainFrame.Items.Add(searchResultItem); this.mainFrame.Items.Add(searchResultItem);
Dispatcher.BeginInvoke((Action)(() => this.mainFrame.SelectedIndex = (this.mainFrame.Items.Count - 1))); Dispatcher.BeginInvoke((Action)(() => this.mainFrame.SelectedIndex = (this.mainFrame.Items.Count - 1)));
@ -84,6 +107,19 @@ namespace ENI2
ClosableTabItem tabItem = sender as ClosableTabItem; ClosableTabItem tabItem = sender as ClosableTabItem;
if(tabItem != null) if(tabItem != null)
{ {
if(lockedCores.ContainsKey(tabItem))
{
try
{
App.LockingServiceClient.Unlock(lockedCores[tabItem], this.userEntity.Id.Value);
lockedCores.Remove(tabItem);
}
catch(Exception ex)
{
_log.ErrorFormat("LockingService.Unlock: {0}", ex.Message);
}
}
DetailRootControl drc = tabItem.Content as DetailRootControl; DetailRootControl drc = tabItem.Content as DetailRootControl;
if (openTabs.ContainsKey(drc.Core.Id.Value)) if (openTabs.ContainsKey(drc.Core.Id.Value))
openTabs.Remove(drc.Core.Id.Value); openTabs.Remove(drc.Core.Id.Value);
@ -119,6 +155,19 @@ namespace ENI2
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{ {
try
{
// unlock all cores
foreach (ClosableTabItem tabItem in this.lockedCores.Keys)
{
App.LockingServiceClient.Unlock(lockedCores[tabItem], this.userEntity.Id.Value);
}
}
catch(Exception ex)
{
_log.ErrorFormat("LockingService.Unlock: {0}", ex.Message);
}
DBManager.Instance.Disconnect(); DBManager.Instance.Disconnect();
Properties.Settings.Default.MainWindowPlacement = this.GetPlacement(); Properties.Settings.Default.MainWindowPlacement = this.GetPlacement();
Properties.Settings.Default.Save(); Properties.Settings.Default.Save();

View File

@ -390,6 +390,16 @@ namespace ENI2.Properties {
} }
} }
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
public static System.Drawing.Bitmap mail_forward {
get {
object obj = ResourceManager.GetObject("mail_forward", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary> /// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap. /// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary> /// </summary>
@ -1363,6 +1373,15 @@ namespace ENI2.Properties {
} }
} }
/// <summary>
/// Looks up a localized string similar to Send to NSW.
/// </summary>
public static string textSendToNSW {
get {
return ResourceManager.GetString("textSendToNSW", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Ship services. /// Looks up a localized string similar to Ship services.
/// </summary> /// </summary>

View File

@ -634,4 +634,10 @@
<data name="textRequestTimedOut" xml:space="preserve"> <data name="textRequestTimedOut" xml:space="preserve">
<value>Request timed out</value> <value>Request timed out</value>
</data> </data>
<data name="mail_forward" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\mail_forward.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="textSendToNSW" xml:space="preserve">
<value>Send to NSW</value>
</data>
</root> </root>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -10,7 +10,7 @@
<xs:complexType name="CoreLock"> <xs:complexType name="CoreLock">
<xs:sequence> <xs:sequence>
<xs:element minOccurs="0" name="CoreId" type="ser:guid" /> <xs:element minOccurs="0" name="CoreId" type="ser:guid" />
<xs:element minOccurs="0" name="UserId" nillable="true" type="xs:string" /> <xs:element minOccurs="0" name="UserId" type="ser:guid" />
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
<xs:element name="CoreLock" nillable="true" type="tns:CoreLock" /> <xs:element name="CoreLock" nillable="true" type="tns:CoreLock" />

View File

@ -7,22 +7,22 @@
<xs:complexType> <xs:complexType>
<xs:sequence> <xs:sequence>
<xs:element xmlns:q1="http://schemas.microsoft.com/2003/10/Serialization/" minOccurs="0" name="messageCoreId" type="q1:guid" /> <xs:element xmlns:q1="http://schemas.microsoft.com/2003/10/Serialization/" minOccurs="0" name="messageCoreId" type="q1:guid" />
<xs:element minOccurs="0" name="userId" nillable="true" type="xs:string" /> <xs:element xmlns:q2="http://schemas.microsoft.com/2003/10/Serialization/" minOccurs="0" name="userId" type="q2:guid" />
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
<xs:element name="LockResponse"> <xs:element name="LockResponse">
<xs:complexType> <xs:complexType>
<xs:sequence> <xs:sequence>
<xs:element minOccurs="0" name="LockResult" nillable="true" type="xs:string" /> <xs:element xmlns:q3="http://schemas.microsoft.com/2003/10/Serialization/" minOccurs="0" name="LockResult" type="q3:guid" />
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
<xs:element name="Unlock"> <xs:element name="Unlock">
<xs:complexType> <xs:complexType>
<xs:sequence> <xs:sequence>
<xs:element xmlns:q2="http://schemas.microsoft.com/2003/10/Serialization/" minOccurs="0" name="messageCoreId" type="q2:guid" /> <xs:element xmlns:q4="http://schemas.microsoft.com/2003/10/Serialization/" minOccurs="0" name="messageCoreId" type="q4:guid" />
<xs:element minOccurs="0" name="userId" nillable="true" type="xs:string" /> <xs:element xmlns:q5="http://schemas.microsoft.com/2003/10/Serialization/" minOccurs="0" name="userId" type="q5:guid" />
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
@ -39,15 +39,15 @@
<xs:element name="GetLocksResponse"> <xs:element name="GetLocksResponse">
<xs:complexType> <xs:complexType>
<xs:sequence> <xs:sequence>
<xs:element xmlns:q3="http://schemas.datacontract.org/2004/07/bsmd.LockingService" minOccurs="0" name="GetLocksResult" nillable="true" type="q3:ArrayOfCoreLock" /> <xs:element xmlns:q6="http://schemas.datacontract.org/2004/07/bsmd.LockingService" minOccurs="0" name="GetLocksResult" nillable="true" type="q6:ArrayOfCoreLock" />
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
<xs:element name="LockRefresh"> <xs:element name="LockRefresh">
<xs:complexType> <xs:complexType>
<xs:sequence> <xs:sequence>
<xs:element xmlns:q4="http://schemas.microsoft.com/2003/10/Serialization/Arrays" minOccurs="0" name="currentLocks" nillable="true" type="q4:ArrayOfguid" /> <xs:element xmlns:q7="http://schemas.microsoft.com/2003/10/Serialization/Arrays" minOccurs="0" name="currentLocks" nillable="true" type="q7:ArrayOfguid" />
<xs:element minOccurs="0" name="userId" nillable="true" type="xs:string" /> <xs:element xmlns:q8="http://schemas.microsoft.com/2003/10/Serialization/" minOccurs="0" name="userId" type="q8:guid" />
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
@ -61,7 +61,7 @@
<xs:sequence> <xs:sequence>
<xs:element minOccurs="0" name="msg" nillable="true" type="xs:string" /> <xs:element minOccurs="0" name="msg" nillable="true" type="xs:string" />
<xs:element minOccurs="0" name="host" nillable="true" type="xs:string" /> <xs:element minOccurs="0" name="host" nillable="true" type="xs:string" />
<xs:element minOccurs="0" name="userId" nillable="true" type="xs:string" /> <xs:element xmlns:q9="http://schemas.microsoft.com/2003/10/Serialization/" minOccurs="0" name="userId" type="q9:guid" />
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>

View File

@ -26,7 +26,7 @@ namespace ENI2.LockingServiceReference {
private System.Guid CoreIdField; private System.Guid CoreIdField;
[System.Runtime.Serialization.OptionalFieldAttribute()] [System.Runtime.Serialization.OptionalFieldAttribute()]
private string UserIdField; private System.Guid UserIdField;
[global::System.ComponentModel.BrowsableAttribute(false)] [global::System.ComponentModel.BrowsableAttribute(false)]
public System.Runtime.Serialization.ExtensionDataObject ExtensionData { public System.Runtime.Serialization.ExtensionDataObject ExtensionData {
@ -52,12 +52,12 @@ namespace ENI2.LockingServiceReference {
} }
[System.Runtime.Serialization.DataMemberAttribute()] [System.Runtime.Serialization.DataMemberAttribute()]
public string UserId { public System.Guid UserId {
get { get {
return this.UserIdField; return this.UserIdField;
} }
set { set {
if ((object.ReferenceEquals(this.UserIdField, value) != true)) { if ((this.UserIdField.Equals(value) != true)) {
this.UserIdField = value; this.UserIdField = value;
this.RaisePropertyChanged("UserId"); this.RaisePropertyChanged("UserId");
} }
@ -79,16 +79,16 @@ namespace ENI2.LockingServiceReference {
public interface IService { public interface IService {
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/Lock", ReplyAction="http://tempuri.org/IService/LockResponse")] [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/Lock", ReplyAction="http://tempuri.org/IService/LockResponse")]
string Lock(System.Guid messageCoreId, string userId); System.Guid Lock(System.Guid messageCoreId, System.Guid userId);
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/Lock", ReplyAction="http://tempuri.org/IService/LockResponse")] [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/Lock", ReplyAction="http://tempuri.org/IService/LockResponse")]
System.Threading.Tasks.Task<string> LockAsync(System.Guid messageCoreId, string userId); System.Threading.Tasks.Task<System.Guid> LockAsync(System.Guid messageCoreId, System.Guid userId);
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/Unlock", ReplyAction="http://tempuri.org/IService/UnlockResponse")] [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/Unlock", ReplyAction="http://tempuri.org/IService/UnlockResponse")]
void Unlock(System.Guid messageCoreId, string userId); void Unlock(System.Guid messageCoreId, System.Guid userId);
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/Unlock", ReplyAction="http://tempuri.org/IService/UnlockResponse")] [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/Unlock", ReplyAction="http://tempuri.org/IService/UnlockResponse")]
System.Threading.Tasks.Task UnlockAsync(System.Guid messageCoreId, string userId); System.Threading.Tasks.Task UnlockAsync(System.Guid messageCoreId, System.Guid userId);
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/GetLocks", ReplyAction="http://tempuri.org/IService/GetLocksResponse")] [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/GetLocks", ReplyAction="http://tempuri.org/IService/GetLocksResponse")]
ENI2.LockingServiceReference.CoreLock[] GetLocks(); ENI2.LockingServiceReference.CoreLock[] GetLocks();
@ -97,16 +97,16 @@ namespace ENI2.LockingServiceReference {
System.Threading.Tasks.Task<ENI2.LockingServiceReference.CoreLock[]> GetLocksAsync(); System.Threading.Tasks.Task<ENI2.LockingServiceReference.CoreLock[]> GetLocksAsync();
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/LockRefresh", ReplyAction="http://tempuri.org/IService/LockRefreshResponse")] [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/LockRefresh", ReplyAction="http://tempuri.org/IService/LockRefreshResponse")]
void LockRefresh(System.Guid[] currentLocks, string userId); void LockRefresh(System.Guid[] currentLocks, System.Guid userId);
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/LockRefresh", ReplyAction="http://tempuri.org/IService/LockRefreshResponse")] [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/LockRefresh", ReplyAction="http://tempuri.org/IService/LockRefreshResponse")]
System.Threading.Tasks.Task LockRefreshAsync(System.Guid[] currentLocks, string userId); System.Threading.Tasks.Task LockRefreshAsync(System.Guid[] currentLocks, System.Guid userId);
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/Log", ReplyAction="http://tempuri.org/IService/LogResponse")] [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/Log", ReplyAction="http://tempuri.org/IService/LogResponse")]
void Log(string msg, string host, string userId); void Log(string msg, string host, System.Guid userId);
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/Log", ReplyAction="http://tempuri.org/IService/LogResponse")] [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/Log", ReplyAction="http://tempuri.org/IService/LogResponse")]
System.Threading.Tasks.Task LogAsync(string msg, string host, string userId); System.Threading.Tasks.Task LogAsync(string msg, string host, System.Guid userId);
} }
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
@ -136,19 +136,19 @@ namespace ENI2.LockingServiceReference {
base(binding, remoteAddress) { base(binding, remoteAddress) {
} }
public string Lock(System.Guid messageCoreId, string userId) { public System.Guid Lock(System.Guid messageCoreId, System.Guid userId) {
return base.Channel.Lock(messageCoreId, userId); return base.Channel.Lock(messageCoreId, userId);
} }
public System.Threading.Tasks.Task<string> LockAsync(System.Guid messageCoreId, string userId) { public System.Threading.Tasks.Task<System.Guid> LockAsync(System.Guid messageCoreId, System.Guid userId) {
return base.Channel.LockAsync(messageCoreId, userId); return base.Channel.LockAsync(messageCoreId, userId);
} }
public void Unlock(System.Guid messageCoreId, string userId) { public void Unlock(System.Guid messageCoreId, System.Guid userId) {
base.Channel.Unlock(messageCoreId, userId); base.Channel.Unlock(messageCoreId, userId);
} }
public System.Threading.Tasks.Task UnlockAsync(System.Guid messageCoreId, string userId) { public System.Threading.Tasks.Task UnlockAsync(System.Guid messageCoreId, System.Guid userId) {
return base.Channel.UnlockAsync(messageCoreId, userId); return base.Channel.UnlockAsync(messageCoreId, userId);
} }
@ -160,19 +160,19 @@ namespace ENI2.LockingServiceReference {
return base.Channel.GetLocksAsync(); return base.Channel.GetLocksAsync();
} }
public void LockRefresh(System.Guid[] currentLocks, string userId) { public void LockRefresh(System.Guid[] currentLocks, System.Guid userId) {
base.Channel.LockRefresh(currentLocks, userId); base.Channel.LockRefresh(currentLocks, userId);
} }
public System.Threading.Tasks.Task LockRefreshAsync(System.Guid[] currentLocks, string userId) { public System.Threading.Tasks.Task LockRefreshAsync(System.Guid[] currentLocks, System.Guid userId) {
return base.Channel.LockRefreshAsync(currentLocks, userId); return base.Channel.LockRefreshAsync(currentLocks, userId);
} }
public void Log(string msg, string host, string userId) { public void Log(string msg, string host, System.Guid userId) {
base.Channel.Log(msg, host, userId); base.Channel.Log(msg, host, userId);
} }
public System.Threading.Tasks.Task LogAsync(string msg, string host, string userId) { public System.Threading.Tasks.Task LogAsync(string msg, string host, System.Guid userId) {
return base.Channel.LogAsync(msg, host, userId); return base.Channel.LogAsync(msg, host, userId);
} }
} }

View File

@ -10,6 +10,7 @@ using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using bsmd.database; using bsmd.database;
using System.Windows.Data;
namespace ENI2 namespace ENI2
{ {
@ -20,6 +21,7 @@ namespace ENI2
{ {
private List<MessageCore> anmeldungen = new List<MessageCore>(); private List<MessageCore> anmeldungen = new List<MessageCore>();
private object searchLock = new object();
#region Construction #region Construction
@ -77,8 +79,16 @@ namespace ENI2
if (from.HasValue || to.HasValue) if (from.HasValue || to.HasValue)
filterDict.Add(MessageCore.SearchFilterType.FILTER_ETA, string.Format("{0}:{1}", from?.ToString() ?? "", to?.ToString() ?? "")); filterDict.Add(MessageCore.SearchFilterType.FILTER_ETA, string.Format("{0}:{1}", from?.ToString() ?? "", to?.ToString() ?? ""));
// menge suchen
int? resultLimit = null;
int? expectedResultNum = DBManager.Instance.GetNumCoresWithFilters(filterDict);
if ((expectedResultNum ?? 0) > 100)
resultLimit = 100;
// suche auslösen // suche auslösen
this.anmeldungen = DBManager.Instance.GetMessageCoresWithFilters(filterDict); this.anmeldungen = DBManager.Instance.GetMessageCoresWithFilters(filterDict, resultLimit);
BindingOperations.EnableCollectionSynchronization(this.anmeldungen, this.searchLock); // prevent sync lock exceptions (trat bei Sandra auf)
if (App.UserId.HasValue) if (App.UserId.HasValue)
{ {
@ -102,7 +112,7 @@ namespace ENI2
// ergebnis anzeigen // ergebnis anzeigen
this.dataGrid.ItemsSource = this.anmeldungen; this.dataGrid.ItemsSource = this.anmeldungen;
this.searchResultLabel.Content = (this.anmeldungen.Count > 0) ? string.Format("{0} results found.", this.anmeldungen.Count) : "no results"; this.searchResultLabel.Content = ((expectedResultNum ?? 0) > 0) ? string.Format("{0} results found, {1} displayed.", (expectedResultNum ?? 0), this.anmeldungen.Count) : "no results";
} }

View File

@ -36,7 +36,9 @@
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!-- This ContentPresenter automatically binds to the Content of the Window --> <!-- This ContentPresenter automatically binds to the Content of the Window -->
<ContentPresenter /> <ContentPresenter />
<!-- TODO das hier lokalisieren! -->
<StackPanel Grid.Row="1" Orientation="Horizontal" Margin="5" HorizontalAlignment="Right"> <StackPanel Grid.Row="1" Orientation="Horizontal" Margin="5" HorizontalAlignment="Right">
<Button Width="80" Content="Add" Name="buttonAdd" Margin="0,0,10,0" Visibility="Hidden" />
<Button Width="80" Content="OK" IsDefault="True" Name="buttonOK" Margin="0,0,10,0" /> <Button Width="80" Content="OK" IsDefault="True" Name="buttonOK" Margin="0,0,10,0" />
<Button Width="80" Content="Cancel" IsCancel="True" Name="buttonCancel" /> <Button Width="80" Content="Cancel" IsCancel="True" Name="buttonCancel" />
</StackPanel> </StackPanel>

Binary file not shown.

View File

@ -11,7 +11,7 @@
<userSettings> <userSettings>
<CoreDeleteTool.Properties.Settings> <CoreDeleteTool.Properties.Settings>
<setting name="ConnectionString" serializeAs="String"> <setting name="ConnectionString" serializeAs="String">
<value>replace me!</value> <value>Data Source=(localdb)\Projects;Initial Catalog=nsw;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False</value>
</setting> </setting>
</CoreDeleteTool.Properties.Settings> </CoreDeleteTool.Properties.Settings>
</userSettings> </userSettings>

View File

@ -33,6 +33,9 @@
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<PropertyGroup>
<ApplicationIcon>application_delete.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
@ -97,6 +100,9 @@
<Name>bsmd.database</Name> <Name>bsmd.database</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Content Include="application_delete.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -12,7 +12,7 @@ namespace CoreDeleteTool.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@ -25,7 +25,8 @@ namespace CoreDeleteTool.Properties {
[global::System.Configuration.UserScopedSettingAttribute()] [global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("replace me!")] [global::System.Configuration.DefaultSettingValueAttribute("Data Source=(localdb)\\Projects;Initial Catalog=nsw;Integrated Security=True;Conne" +
"ct Timeout=30;Encrypt=False;TrustServerCertificate=False")]
public string ConnectionString { public string ConnectionString {
get { get {
return ((string)(this["ConnectionString"])); return ((string)(this["ConnectionString"]));

View File

@ -3,7 +3,7 @@
<Profiles /> <Profiles />
<Settings> <Settings>
<Setting Name="ConnectionString" Type="System.String" Scope="User"> <Setting Name="ConnectionString" Type="System.String" Scope="User">
<Value Profile="(Default)">replace me!</Value> <Value Profile="(Default)">Data Source=(localdb)\Projects;Initial Catalog=nsw;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False</Value>
</Setting> </Setting>
</Settings> </Settings>
</SettingsFile> </SettingsFile>

View File

@ -62,7 +62,7 @@ namespace bsmd.ExcelReadService
} }
_log.DebugFormat("{0} named ranges found at Workbook level", bookCnt); _log.DebugFormat("{0} named ranges found at Workbook level", bookCnt);
/*
foreach(Worksheet ws in _portcall.Worksheets) foreach(Worksheet ws in _portcall.Worksheets)
{ {
int wsCnt = 0; int wsCnt = 0;
@ -82,7 +82,7 @@ namespace bsmd.ExcelReadService
if (wsCnt > 0) if (wsCnt > 0)
_log.DebugFormat("{0} named ranges found in Worksheet {1}", wsCnt, ws.Name); _log.DebugFormat("{0} named ranges found in Worksheet {1}", wsCnt, ws.Name);
} }
*/
} }
@ -114,9 +114,9 @@ namespace bsmd.ExcelReadService
if (val2 != null) if (val2 != null)
return val2.ToString().Trim(); return val2.ToString().Trim();
} }
catch(COMException) catch(COMException ex)
{ {
_log.WarnFormat("COMException reading field:{0}", lookup); _log.WarnFormat("COMException reading field {0}: {1}", lookup, ex.ErrorCode);
} }
return null; return null;
} }

View File

@ -165,10 +165,18 @@ namespace bsmd.ExcelReadService
#region class LocodeEntry #region class LocodeEntry
public class LocodeEntry public class LocodeEntry : IComparable
{ {
public string Locode { get; set; } public string Locode { get; set; }
public string Name { get; set; } public string Name { get; set; }
public int CompareTo(object otherLocode)
{
if (otherLocode is LocodeEntry)
return Locode.CompareTo(((LocodeEntry)otherLocode).Locode);
else
return 0;
}
} }
#endregion #endregion

View File

@ -0,0 +1,22 @@
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net"/>
</configSections>
<log4net>
<root>
<level value="DEBUG" />
<appender-ref ref="LogFileAppender" />
</root>
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender" >
<param name="File" value="E:\Temp\LockingService.log" />
<param name="AppendToFile" value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
</log4net>
</configuration>

View File

@ -159,10 +159,23 @@ namespace bsmd.database
return result; return result;
} }
public List<MessageCore> GetMessageCoresWithFilters(Dictionary<MessageCore.SearchFilterType, string> filters) public int? GetNumCoresWithFilters(Dictionary<MessageCore.SearchFilterType, string> filters)
{ {
MessageCore aMessageCore = new MessageCore(); MessageCore aMessageCore = new MessageCore();
SqlCommand cmd = new SqlCommand(); SqlCommand cmd = new SqlCommand();
aMessageCore.PrepareCountCmd(cmd, Message.LoadFilter.SEARCH_CORE_FILTERS, filters);
int? result = this.PerformReadIntQuery(cmd);
return result;
}
public List<MessageCore> GetMessageCoresWithFilters(Dictionary<MessageCore.SearchFilterType, string> filters, int? limit = null)
{
MessageCore aMessageCore = new MessageCore();
SqlCommand cmd = new SqlCommand();
if (limit.HasValue && (limit.Value > 0))
aMessageCore.ResultLimit = limit;
aMessageCore.PrepareLoadCommand(cmd, Message.LoadFilter.SEARCH_CORE_FILTERS, filters); aMessageCore.PrepareLoadCommand(cmd, Message.LoadFilter.SEARCH_CORE_FILTERS, filters);
SqlDataReader reader = this.PerformCommand(cmd); SqlDataReader reader = this.PerformCommand(cmd);
@ -416,7 +429,9 @@ namespace bsmd.database
{ {
if(messageCore == null) return; if(messageCore == null) return;
foreach(Message message in this.GetMessagesForCore(messageCore, MessageLoad.ALL)) List<Message> coreMessages = this.GetMessagesForCore(messageCore, MessageLoad.ALL);
foreach (Message message in coreMessages)
{ {
if (message is ISublistContainer) if (message is ISublistContainer)
{ {
@ -534,6 +549,11 @@ namespace bsmd.database
List<DatabaseEntity> statList = msgClass.LoadList(reader); List<DatabaseEntity> statList = msgClass.LoadList(reader);
foreach (DatabaseEntity derivedMessage in statList) foreach (DatabaseEntity derivedMessage in statList)
{ {
if(message.MessageNotificationClass == Message.NotificationClass.HAZD)
{
if(derivedMessage is HAZ)
((HAZ)derivedMessage).IsDeparture = true;
}
message.Elements.Add(derivedMessage); message.Elements.Add(derivedMessage);
derivedMessage.MessageHeader = message; derivedMessage.MessageHeader = message;
this.LoadDependingLists(derivedMessage); this.LoadDependingLists(derivedMessage);
@ -1027,6 +1047,32 @@ namespace bsmd.database
return result; return result;
} }
internal int? PerformReadIntQuery(SqlCommand cmd)
{
int? result = null;
lock (this._lock)
{
try
{
cmd.Connection = this._con;
result = (int?)cmd.ExecuteScalar();
}
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 #endregion
#endregion #endregion

View File

@ -11,7 +11,6 @@ using System;
using System.Data; using System.Data;
using System.Data.SqlClient; using System.Data.SqlClient;
using System.Linq; using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
@ -57,7 +56,7 @@ namespace bsmd.database
/// <summary> /// <summary>
/// SQL Table name to construct queries /// SQL Table name to construct queries
/// </summary> /// </summary>
public string Tablename { get { return this.tablename; } } public virtual string Tablename { get { return this.tablename; } }
/// <summary> /// <summary>
/// primary key /// primary key
@ -87,10 +86,21 @@ namespace bsmd.database
scmd.Parameters.AddWithValue("@ID", this.Id); scmd.Parameters.AddWithValue("@ID", this.Id);
} }
/// <summary>
/// Ergebnismenge begrenzen: NULL = kein Limit. Abgeleitete Klassen *können* diesen Parameter berücksichtigen
/// </summary>
public int? ResultLimit { get; set; }
public abstract void PrepareLoadCommand(IDbCommand cmd, Message.LoadFilter filter, params object[] criteria); public abstract void PrepareLoadCommand(IDbCommand cmd, Message.LoadFilter filter, params object[] criteria);
public abstract List<DatabaseEntity> LoadList(IDataReader reader); public abstract List<DatabaseEntity> LoadList(IDataReader reader);
public virtual void PrepareCountCmd(IDbCommand cmd, Message.LoadFilter filter, params object[] criteria)
{
SqlCommand scmd = cmd as SqlCommand;
scmd.CommandText = string.Format("SELECT COUNT(*) FROM {0}", Tablename);
}
/// <summary> /// <summary>
/// Überprüft eingegangene Meldeklassen auf Fehlerkonditionen /// Überprüft eingegangene Meldeklassen auf Fehlerkonditionen
/// </summary> /// </summary>

View File

@ -7,9 +7,7 @@
// //
// Copyright (c) 2015 Informatikbüro Daniel Schick. All rights reserved. // Copyright (c) 2015 Informatikbüro Daniel Schick. All rights reserved.
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient; using System.Data.SqlClient;
namespace bsmd.database namespace bsmd.database
@ -104,7 +102,7 @@ namespace bsmd.database
#region DatabaseEntity implementation #region DatabaseEntity implementation
public new string Tablename public override string Tablename
{ {
get get
{ {

View File

@ -311,16 +311,41 @@ namespace bsmd.database
public override void PrepareLoadCommand(System.Data.IDbCommand cmd, Message.LoadFilter filter, params object[] criteria) public override void PrepareLoadCommand(System.Data.IDbCommand cmd, Message.LoadFilter filter, params object[] criteria)
{ {
StringBuilder sb = new StringBuilder( StringBuilder sb = new StringBuilder("SELECT ");
string.Format("SELECT [{0}].[Id], [{0}].[VisitId], [{0}].[TransitId], [{0}].[IMO], [{0}].[ENI], [{0}].[PoC], [{0}].[Portname], " + if (this.ResultLimit.HasValue && this.ResultLimit.Value > 0)
"[{0}].[ETA], [{0}].[CustomerId], [{0}].[Previous], [{0}].[Next], [{0}].[IsTransit], [{0}].[Wetris_zz_56_datensatz_id], [{0}].[BSMDStatus], " + {
"[{0}].[InitialHIS], [{0}].[HerbergFormGuid], [{0}].[HerbergFormTemplateGuid], [{0}].[HerbergReportType], [{0}].[HerbergEmailContactReportingVessel], " + sb.Append(string.Format("TOP {0} ", this.ResultLimit));
"[{0}].[HerbergEmail24HrsContact], [{0}].[ETAKielCanal], [{0}].[HerbergRevDate], [{0}].[ReportStatus], [{0}].[SietasSheetVersion], [{0}].[Incoming], " + }
"[{0}].[DefaultReportingPartyId], [{0}].[Created], [{0}].[Changed], [{0}].[CreateExcel], [{0}].[EditedBy], [{0}].[TicketNo], " +
"[{0}].[Cancelled], [{0}].[VisitIdOrTransitIdCancellable], [{0}].[BlockedNotificationClasses], [{0}].[FreeNotificationClasses], " +
"[{0}].[OwnNotificationClasses], [{0}].[StatusCheckErrorCode], [{0}].[StatusCheckErrorMessage], [{0}].[QueryNSWStatus] FROM {0} ",
this.Tablename));
sb.Append(string.Format("[{0}].[Id], [{0}].[VisitId], [{0}].[TransitId], [{0}].[IMO], [{0}].[ENI], [{0}].[PoC], [{0}].[Portname], " +
"[{0}].[ETA], [{0}].[CustomerId], [{0}].[Previous], [{0}].[Next], [{0}].[IsTransit], [{0}].[Wetris_zz_56_datensatz_id], [{0}].[BSMDStatus], " +
"[{0}].[InitialHIS], [{0}].[HerbergFormGuid], [{0}].[HerbergFormTemplateGuid], [{0}].[HerbergReportType], [{0}].[HerbergEmailContactReportingVessel], " +
"[{0}].[HerbergEmail24HrsContact], [{0}].[ETAKielCanal], [{0}].[HerbergRevDate], [{0}].[ReportStatus], [{0}].[SietasSheetVersion], [{0}].[Incoming], " +
"[{0}].[DefaultReportingPartyId], [{0}].[Created], [{0}].[Changed], [{0}].[CreateExcel], [{0}].[EditedBy], [{0}].[TicketNo], " +
"[{0}].[Cancelled], [{0}].[VisitIdOrTransitIdCancellable], [{0}].[BlockedNotificationClasses], [{0}].[FreeNotificationClasses], " +
"[{0}].[OwnNotificationClasses], [{0}].[StatusCheckErrorCode], [{0}].[StatusCheckErrorMessage], [{0}].[QueryNSWStatus] FROM {0} ",
this.Tablename));
this.SetFilters(sb, cmd, filter, criteria);
sb.Append(" ORDER BY ETA DESC");
cmd.CommandText = sb.ToString();
}
public override void PrepareCountCmd(IDbCommand cmd, Message.LoadFilter filter, params object[] criteria)
{
StringBuilder sb = new StringBuilder("SELECT COUNT(*) FROM ");
sb.Append(this.Tablename);
sb.Append(" ");
this.SetFilters(sb, cmd, filter, criteria);
cmd.CommandText = sb.ToString();
}
private void SetFilters(StringBuilder sb, IDbCommand cmd, Message.LoadFilter filter, params object[] criteria)
{
switch (filter) switch (filter)
{ {
case Message.LoadFilter.WETRIS_SHIP_ID: case Message.LoadFilter.WETRIS_SHIP_ID:
@ -337,7 +362,7 @@ namespace bsmd.database
} }
case Message.LoadFilter.BSMDSTATUS: case Message.LoadFilter.BSMDSTATUS:
{ {
sb.Append("WHERE BSMDStatus = @STATUS ORDER BY ETA DESC"); sb.Append("WHERE BSMDStatus = @STATUS");
((SqlCommand)cmd).Parameters.AddWithValue("@STATUS", criteria[0]); ((SqlCommand)cmd).Parameters.AddWithValue("@STATUS", criteria[0]);
break; break;
} }
@ -391,7 +416,7 @@ namespace bsmd.database
Dictionary<SearchFilterType, string> searchDict = criteria[0] as Dictionary<SearchFilterType, string>; Dictionary<SearchFilterType, string> searchDict = criteria[0] as Dictionary<SearchFilterType, string>;
if (searchDict != null && (searchDict.Count > 0)) if (searchDict != null && (searchDict.Count > 0))
{ {
if(searchDict.ContainsKey(SearchFilterType.FILTER_SHIPNAME)) if (searchDict.ContainsKey(SearchFilterType.FILTER_SHIPNAME))
{ {
// perform STAT join // perform STAT join
sb.Append(" JOIN MessageHeader mh ON MessageCore.Id = mh.MessageCoreId JOIN STAT ON mh.Id = STAT.MessageHeaderId"); sb.Append(" JOIN MessageHeader mh ON MessageCore.Id = mh.MessageCoreId JOIN STAT ON mh.Id = STAT.MessageHeaderId");
@ -414,13 +439,13 @@ namespace bsmd.database
sb.Append(" (ETA > @SEARCHFROM) "); sb.Append(" (ETA > @SEARCHFROM) ");
((SqlCommand)cmd).Parameters.AddWithValue("@SEARCHFROM", from.Value.FromUnixTimeStamp()); ((SqlCommand)cmd).Parameters.AddWithValue("@SEARCHFROM", from.Value.FromUnixTimeStamp());
} }
if(to.HasValue && !from.HasValue) if (to.HasValue && !from.HasValue)
{ {
sb.Append(" (ETA < @SEARCHTO) "); sb.Append(" (ETA < @SEARCHTO) ");
((SqlCommand)cmd).Parameters.AddWithValue("@SEARCHTO", to.Value.FromUnixTimeStamp()); ((SqlCommand)cmd).Parameters.AddWithValue("@SEARCHTO", to.Value.FromUnixTimeStamp());
} }
if(from.HasValue && to.HasValue) if (from.HasValue && to.HasValue)
{ {
sb.Append(" (ETA > @SEARCHFROM AND ETA < @SEARCHTO) "); sb.Append(" (ETA > @SEARCHFROM AND ETA < @SEARCHTO) ");
((SqlCommand)cmd).Parameters.AddWithValue("@SEARCHFROM", from.Value.FromUnixTimeStamp()); ((SqlCommand)cmd).Parameters.AddWithValue("@SEARCHFROM", from.Value.FromUnixTimeStamp());
@ -465,18 +490,15 @@ namespace bsmd.database
if (!moreThanOne) moreThanOne = true; if (!moreThanOne) moreThanOne = true;
} }
} }
sb.Append(" ORDER BY ETA DESC");
break; break;
} }
case Message.LoadFilter.ALL: case Message.LoadFilter.ALL:
default: default:
sb.Append(" ORDER BY ETA DESC");
break; break;
} }
cmd.CommandText = sb.ToString();
} }
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>();

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="log4net" version="2.0.7" targetFramework="net45" />
</packages>