data validation: catching and dealing with ConstraintExceptions

cjard

Well-known member
Joined
Apr 25, 2006
Messages
7,081
Programming Experience
10+
The Microsoft website doesnt say much about how we can catch exceptions raised by DataSets when we attempt to insert invalid data into them..

Rather than write all my error handling code manually, I'm wondering how I can catch and deal with the ConstraintException that occurs if I attempt to edit data in the following hierarchy:

VB.NET:
[FONT=Courier New][binding navigator]---------------[/FONT]
[FONT=Courier New]                                \[/FONT]
[FONT=Courier New]                                V[/FONT]
[FONT=Courier New][controls such as textboxes] -> [binding source] -> [data table][/FONT]

Currently, if i have 2 records in my DataTable, and hence scrollable using the binding navigator.. suppose I scroll to the first of them and change the primary key value so that it conflicts with the other entry.
The exception will arise when I again scroll away from the current record with the bindingnavigator.. as part of it scrolling, it automatically performs an EndEdit on the bindingsource, and a constraintexception is thrown

Unfortunately, I cant catch this exception, because the code that throws it is not stuff I wrote; the designer might have written it as part of its automatic assignment/creation of the binding nav.

Now, i could write code into the RowChanging event of the datatable, inspect the new data, see if it conflicts etc, but it sounds like a lot of work when all that would be required would be to catch the exception and abort the addition.. Where do i catch the exception?


---
For example, If i force the following exception to appear, I cant even get the debugger to break as soon as it's thrown and show me the code that throws it:

VB.NET:
System.Data.ConstraintException was unhandled
  Message="Column 'ADDRESS_REF, EFFECTIVE_DATE' is constrained to be unique.  Value '00004592, 09/09/2006 00:00:00' is already present."
  Source="System.Data"
  StackTrace:
       at System.Data.UniqueConstraint.CheckConstraint(DataRow row, DataRowAction action)
       at System.Data.DataTable.RaiseRowChanging(DataRowChangeEventArgs args, DataRow eRow, DataRowAction eAction, Boolean fireEvent)
       at System.Data.DataTable.SetNewRecordWorker(DataRow row, Int32 proposedRecord, DataRowAction action, Boolean isInMerge, Int32 position, Boolean fireEvent, Exception& deferredException)
       at System.Data.DataTable.SetNewRecord(DataRow row, Int32 proposedRecord, DataRowAction action, Boolean isInMerge, Boolean fireEvent)
       at System.Data.DataRow.EndEdit()
       at System.Data.DataRowView.EndEdit()
       at System.Windows.Forms.CurrencyManager.EndCurrentEdit()
       at System.Windows.Forms.CurrencyManager.ChangeRecordState(Int32 newPosition, Boolean validating, Boolean endCurrentEdit, Boolean firePositionChange, Boolean pullData)
       at System.Windows.Forms.CurrencyManager.set_Position(Int32 value)
       at System.Windows.Forms.BindingSource.MoveNext()
       at System.Windows.Forms.BindingNavigator.OnMoveNext(Object sender, EventArgs e)
       at System.Windows.Forms.ToolStripItem.RaiseEvent(Object key, EventArgs e)
       at System.Windows.Forms.ToolStripButton.OnClick(EventArgs e)
       at System.Windows.Forms.ToolStripItem.HandleClick(EventArgs e)
       at System.Windows.Forms.ToolStripItem.HandleMouseUp(MouseEventArgs e)
       at System.Windows.Forms.ToolStripItem.FireEventInteractive(EventArgs e, ToolStripItemEventType met)
       at System.Windows.Forms.ToolStripItem.FireEvent(EventArgs e, ToolStripItemEventType met)
       at System.Windows.Forms.ToolStrip.OnMouseUp(MouseEventArgs mea)
       at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
       at System.Windows.Forms.ToolStrip.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(ApplicationContext context)
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
       at DDHub.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81
       at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
 
Infact.. It appears that I cant even write my own event handling code, because the scenario I describe above causes a ConstraintException to be raised without firing the RowChanging event. Does this mean I have to unlink all my BindingNavigator buttons from their default action and reprogram in that exact same action myself, only wrapped in a Try?


At this point, I really feel that data access in .NET2, and all these wonderful helper methods and new ways of doing things are a crock of ****. The Data Walkthroughs on Microsoft's site seem to pick a careful path of "what works" through a sea of stuff that looks useful but is broken or works in the most retarded way imaginable. If you want to write a simple app with no related data and no primary keys youre in luck, otherwise youre wasting time.

I have to ask:

Am i just asking too much? Am I doing data access in the wrong way? Am I too thick to own a computer?
 
Does this mean I have to unlink all my BindingNavigator buttons from their default action and reprogram in that exact same action myself, only wrapped in a Try?

Yes.

Welcome to a world of automated assistance, where if you want to do anything other than the default, the legwork you have to put in causes more work than the automation solved.
 
Back
Top