JimmyJimm JimmyJimm - 4 months ago 8
Vb.net Question

How to show error message on forms project when its already catched in library

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
Try
resu = createArticle.ProcessArticle(data)
Catch sqlex As Exception
pic.Invoke(Sub() MessageBox.Show(pic, sqlex.Message))
Finally
'--Close form once done (on GUI thread)
pic.Invoke(New Action(Sub() pic.Close()))
End Try
Return resu
End Function)
'Show circural form
pic.ShowDialog()
Task.WaitAll(tsk)

if tsk.Result = true Then
...


This comes from library project:

Public Function ProcessArticle(data as Data) As Boolean
Dim result = false

Using connection As New SqlConnection(strcon)
Try
connection.Open()
Dim transaction As SqlTransaction
transaction = connection.BeginTransaction()
.....
transaction.Commit()
result=true
Catch ex As Exception
result = False
transaction.Rollback()
End Try
End Using

return result
End Function

Answer

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.

EDIT

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

EDIT 2

More on the Throw Statement:

A Throw statement with no expression can only be used in a Catch statement, in which case the statement rethrows the exception currently being handled by the Catch statement.