Have some windows form with nice circural progress bar which i show user during long database function process. There is also task which calls function which inside i got query with transaction and there is catch implemented to rollback if it fails and return either true/false about state of process after finished. I didn't place there memssage box to show error as it's not adviced to store message boxes along in library projects so i would like to show this error on my task level function (in catch). However since i am catching error inside my function i am not able to show it (catch it) on the task's catch. How to accomplish that?
The only idea in my head is to instead of returning only result also return catched error message with use of Tuple like this: Tuple(Of Boolean, String). So i would be able to return two things: result and error message text. I am not so sure if this is right way to do such things. Looking for your advice.
This comes from windows forms project:
Dim pic As New CircuralWindowsForms(eCircularProgressType.Donut)
Dim tsk As Task(Of Boolean) = Task.Factory.StartNew(Of Boolean)(Function()
Dim resu = False
resu = createArticle.ProcessArticle(data)
Catch sqlex As Exception
pic.Invoke(Sub() MessageBox.Show(pic, sqlex.Message))
'--Close form once done (on GUI thread)
pic.Invoke(New Action(Sub() pic.Close()))
'Show circural form
if tsk.Result = true Then
Public Function ProcessArticle(data as Data) As Boolean
Dim result = false
Using connection As New SqlConnection(strcon)
Dim transaction As SqlTransaction
transaction = connection.BeginTransaction()
Catch ex As Exception
result = False
You're right that it would be wrong for your library to display message boxes directly. But that doesn't mean it should swallow exceptions either. In, fact, quite the opposite: you really should let the exception bubble up to the caller, and let the caller decide what to do with it.
With that in mind, I would change the
ProcessArticle function to the following:
Public Sub ProcessArticle(data as Data) Using connection As New SqlConnection(strcon) Try connection.Open() Dim transaction As SqlTransaction transaction = connection.BeginTransaction() ' ..... transaction.Commit() Catch ex As Exception transaction.Rollback() Throw 'Rethrow exception. The caller can decide what to do with it. End Try End Using End Sub
Notice how the exception is still caught to enable the transaction rollback, but the exception is rethrown so that the caller can catch it. This in turn means that you no longer need to return a boolean to indicate success or failure.
Not directly related to your question, but I would further move the code around a little bit so that I don't accidentally try to rollback a transaction before it has even begun (With you current code, ask yourself what would happen if an error occurred while trying to open the connection?):
Public Sub ProcessArticle(data as Data) Using connection As New SqlConnection(strcon) connection.Open() Using transaction = connection.BeginTransaction() Try ' do work here transaction.Commit() Catch ex As Exception transaction.Rollback() Throw 'Rethrow exception. The caller can decide what to do with it. End Try End Using End Using End Sub
More on the Throw Statement:
Throwstatement with no expression can only be used in a
Catchstatement, in which case the statement rethrows the exception currently being handled by the