Exception thrown on close of work period

Hi all,

i’m getting my client crash (v 5.3.0) when i close the workperiod, see the error below.

[Exception Info 1]

Top-level Exception
Type: System.InvalidOperationException
Message: Sequence contains more than one element
Source: System.Core
Stack Trace: at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable1 source) at System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.<>c__141.b__14_2(IEnumerable1 sequence) at System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.ExecuteSingle[TResult](IEnumerable1 query, Expression queryRoot)
at System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute[TResult](Expression expression)
at System.Linq.Queryable.SingleOrDefault[TSource](IQueryable1 source) at Samba.Infrastructure.Data.SqlData.EFWorkspace.Single[T](Expression1 expression, Expression1[] includes) at Samba.Services.Implementations.SettingsModule.ProgramSettings.GetSetting(String valueName) in C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\SettingsModule\ProgramSettings.cs:line 0 at Samba.Services.Implementations.SettingsModule.SettingService.ReadGlobalSetting(String settingName) in C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\SettingsModule\SettingService.cs:line 102 at Samba.Presentation.ClientLibrary.Modules.SettingsModule.ActionProcessors.UpdateProgramSetting.UpdateSetting(ActionData actionData, String settingName, String updateType) in C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Presentation.ClientLibrary\Modules\SettingsModule\ActionProcessors\UpdateProgramSetting.cs:line 35 at Samba.Presentation.ClientLibrary.Modules.SettingsModule.ActionProcessors.UpdateProgramSetting.Process(ActionData actionData, RuleExecutionContext context) in C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Presentation.ClientLibrary\Modules\SettingsModule\ActionProcessors\UpdateProgramSetting.cs:line 26 at Samba.Services.Common.RuleActionTypeRegistry.ProcessAction(String actionType, ActionData actionData, RuleExecutionContext context) in C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Common\RuleActionTypeRegistry.cs:line 39 at Samba.Services.Implementations.AutomationModule.AutomationService.ProcessAction(String actionType, ActionData actionData, RuleExecutionContext context) in C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\AutomationModule\AutomationService.cs:line 42 at Samba.Services.Implementations.AutomationModule.ActionDataBuilder.<>c__DisplayClass13_0.<InvokeWith>b__0() in C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\AutomationModule\ActionDataBuilder.cs:line 76 at System.Windows.Threading.Dispatcher.Invoke(Action callback, DispatcherPriority priority, CancellationToken cancellationToken, TimeSpan timeout) at System.Windows.Threading.Dispatcher.Invoke(Action callback) at Samba.Services.Implementations.AutomationModule.ActionDataBuilder.InvokeWith(AppState appState, RuleExecutionContext context) in C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\AutomationModule\ActionDataBuilder.cs:line 84 at Samba.Services.Implementations.AutomationModule.RuleExecutor.ExecuteWithoutLogging(Object ruleData) in C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\AutomationModule\RuleExecutor.cs:line 125 at Samba.Services.Implementations.AutomationModule.RuleExecutor.ExecuteWith(Object dataParameter) in C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\AutomationModule\RuleExecutor.cs:line 62 at Samba.Services.Implementations.AutomationModule.NotificationService.NotifyEvent(String eventName, Object dataParameter, AppState appState) in C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\AutomationModule\NotificationService.cs:line 26 at Samba.Presentation.Services.Implementations.AutomationModule.NotificationClient.NotifyEvent(String eventName, Object dataObject) at Samba.Presentation.ClientLibrary.Modules.WorkPeriodModule.WorkPeriodsViewModel.OnEndOfDayExecute(String obj) in C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Presentation.ClientLibrary\Modules\WorkPeriodModule\WorkPeriodsViewModel.cs:line 182 at Microsoft.Practices.Prism.Commands.DelegateCommand1.<>c__DisplayClass6.<.ctor>b__2(Object o)
at Microsoft.Practices.Prism.Commands.DelegateCommandBase.Execute(Object parameter)
at Microsoft.Practices.Prism.Commands.DelegateCommandBase.System.Windows.Input.ICommand.Execute(Object parameter)
at MS.Internal.Commands.CommandHelpers.CriticalExecuteCommandSource(ICommandSource commandSource, Boolean userInitiated)
at System.Windows.Controls.Primitives.ButtonBase.OnClick()
at System.Windows.Controls.Button.OnClick()
at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)
at System.Windows.UIElement.OnMouseLeftButtonUpThunk(Object sender, MouseButtonEventArgs e)
at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)
at System.Windows.UIElement.OnMouseUpThunk(Object sender, MouseButtonEventArgs e)
at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
at System.Windows.Input.InputManager.ProcessStagingArea()
at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)

I have tracked it back to our surcharge system.
When a workperiod starts i have a script that checks whether or not it’s a sundary or public holiday and if it is, sets a global setting to confirm it when other actions then use to make different calculations.

Every time a workperiod is stopped, the setting is deleted.

i think maybe the global settings has been set twice or not been deleted correctly. I have no idea why because this has been working for months with no issue at all and no changes have been made recently.

Any help would be appreciated.

It looks like your assumption may be correct.

In SSMS run this query:

SELECT COUNT(Name) AS ItemCount,
       Name        AS SettingName
    FROM dbo.ProgramSettingValues
    GROUP BY Name
    HAVING COUNT(Name) > 1;

if you don’t have SSMS installed, preview this report query in a printer template or report template:

{REPORT SQL DETAILS:SELECT COUNT(Name) AS ItemCount, Name AS SettingName FROM dbo.ProgramSettingValues GROUP BY name HAVING COUNT(Name) > 1:F.ItemCount,F.SettingName}

you will see a list of duplicate program settings if any exist

Thanks @Memo. It’s definitely showing as having two instances of that global setting.

How would i go about resetting it ? i don’t have SSMS installed, would i be able to run a delete command from a report in the same way ?

Would appreciate your thoughts, given the actions above, a duplicate entry could have been created and how I could prevent it occurring again ?

I can upload a task for you to run, no problem.

Is this a setting that is read on startup for anything? I ask because do you need to remove just one, and keep the right one, or just nuke the two and start over?

As for how the duplicate was created it could be two different terminals are writing a setting and aren’t connected to the message server, or two writes at the same time happened.

thanks heaps Memo. In regards to the setting, neither needs to be kept, so it can be nuked and it will recreate on work period start.

maybe that’s what i need to do - add an action to update if it exists as opposed to creating and deleting…

For your action to set the surcharge to zero, try changing “Delete” to “Update”.

Also, the script you’re using to determine if it’s Sunday, is that setting the setting value at all in addition to returning a boolean?

Unzip the file below into %USERPROFILE%\Documents\SambaPOS5\Database Tasks if the directory “Database Tasks” doesn’t exist, create it.

Within SambaPOS navigate to Manage->Settings->Database Tasks and you should see the file as an option to select. Select the task and click “Execute Task”. A backup will be created automatically.

[CBL]Delete_Sunday_Surcharge_Setting.zip (482 Bytes)

It would probably be best to identify the cause.
Maybe a bug in some specific use case…

That’s what I was thinking, too. Two terminals write the same setting before either cache update in time.

The only primary key on that table is the identity column.

Yer, dont think sql wouldn’t have a problem with duplicate setting names in that column, error will be in sambas handling of a duplication in expecting there not to be one.

You see in the exception that SingleOrDefault() is called. If nothing exists then the default object is returned (null for reference types, default for value types - unless they’re nullable but that’s a different beast all together). With “Single”, If there’s more than one element returned it throws an exception. One could use FirstOrDefault() but then one would never know if there are duplicates and if so, whether the right setting is being returned. Saves an exception being thrown, but introduces other issues.

For me, personally, I’m all about finding a natural primary key. The PK would be Name with no identity column; just two columns: Name, Value. But EF has its quirks. It’s possible that when Emre started, EF required an identity column with name “Id” to work. Either way, an exception would still be thrown when inserting a duplicate setting name.

1 Like

Indeed, but then that’s what I am getting as, sql is not the one saying unique values only do issue is the write/update step of flow, with the calling of a setting presuming there is only ever going to be single value.

Which is a valid assumption.

this is the script i use, it only returns a boolean.

Given this is only set on workperiod creation, i honestly don’t know how a duplicate was created. Yes we have multiple terminals but i wouldn’t have though you could run a work period start from two at the same time ?

So there’s no issue with the script insofar as the setting is concerned.

Perhaps, for some reason, the cache on the other terminals isn’t updated and if a work period is close on one terminal and opened on another it could lead to a duplicate setting being created. I’m not 100% sure just how cache updates are pushed.

btw, script worked a treat. thankyou very much for that.

Let me know if i can be of any assistance in tracking down whether or not this is actually a bug.

1 Like

Hey guys, this issue has occurred again and I’ve narrowed down the cause as it has occurred right after a restoration of the database.

I take a copy of the prod db and make changes at home and then restore them at the restaurant. Post that restoration, the issues occurred.

Is it possible that restoring the dB doesn’t clear the global setting but creates a second one ?

Shouldn’t be as backup and restore rather than some sort of import/export, its taking full db tablets and replacing not updating ir merging and global settings are saved in DB.

Ta mate. I’ll try and recreate it but I wonder if there is an issue with the backup restore which doesn’t clear the global settings

The zip contains sql files so beleive it uses the sql backup restore functions so would be surprised if that were the case unless they were specificly left out. Either way would be either not overwritten or completly overwritten.
Would be easy enough to check, just use SQL manager to select and view the settings table.

Backups are executed by the db engine and then zipped by SambaPOS; it is an identical copy of the db. So if duplicate settings existed before, they will persist after the restore.

Have you found this happens only on a given day? Today is Sunday so I’m wondering if there’s something that only executes on Sunday.

In a test environment, I would start with a backup from a day that isn’t Sunday. Set your date to a non-Sunday. Start SambaPOS and start disabling the relevant rules one-by-one. Disable one rule, set date to a Sunday and try and close the work period. If no exception, set date back to non-Sunday, restore the non-Sunday backup, disable a different rule and repeat. Hopefully you might be able to find which rule is executing actions causing a duplicate setting.

For temporarily disabling rules (without deleting mapping) I add a constraint 1 == 2 and make sure “Execute rule If” is “Matches All”.