JimmyJimm JimmyJimm - 3 months ago 22
Vb.net Question

Catch not reached on error

I have main windows form on which i have user control. From there I do some operation related to database. During database process I show user additional windows form so he can see nice circural graphic in meantime. I use task to place mentioned database process and from there if error occurs I want to show error message from try/catch. Unfortunetly MessageBox.Show is not showing up when i do tests - catch is even not reached. Could you help me out what is wrong. I am talking about this line in catch statment:

Catch sqlex As Exception
pic.Invoke(Sub() MessageBox.Show(pic, sqlex.Message))


Here's circural window's form code:

Public Class FrmCircularProgress
Sub New(progressType As DevComponents.DotNetBar.eCircularProgressType)
InitializeComponent()
CircularProgress1.ProgressBarType = progressType
StartCircular()
End Sub

Public Sub StartCircular()
Me.CircularProgress1.IsRunning = True
End Sub

Public Sub StopCircular()
Me.CircularProgress1.IsRunning = False
End Sub
End Class


This is example how i use it with Task:

Dim createArticle As New Artikel

Dim pic As New FrmCircularProgress(eCircularProgressType.Donut)
Dim tsk As Task(Of Boolean) = Task.Factory.StartNew(Of Boolean)(Function()
'--Run lenghty task
Dim resu = False
Try
resu = createArticle.ProcessArticle(_artikelsAndTheirVariationsFinal)
'--Close form once done (on GUI thread)

Catch sqlex As Exception
pic.Invoke(Sub() MessageBox.Show(pic, sqlex.Message))
Finally
pic.Invoke(New Action(Sub() pic.StopCircular()))
pic.Invoke(New Action(Sub() pic.Close()))
End Try

Return resu
End Function)

'--Show the form
pic.ShowDialog()
Task.WaitAll(tsk)
...


And just for you to see example database process in our case ProcessArticle which is returning either true or false

Public Function ProcessArticle(artikel As ArticlesVariations) As Boolean

Dim result = True
Dim strcon = New AppSettingsReader().GetValue("ConnectionString", GetType(System.String)).ToString()

Using connection As New SqlConnection(strcon)
'-- Open generall connection for all the queries
connection.Open()
'-- Make the transaction.
Dim transaction As SqlTransaction
transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted)

Dim newArticleRowId As Integer = 0
Dim articleIndex As Integer = 0
Try
For Each kvp As KeyValuePair(Of Integer, Artikel) In artikel.collection
Dim ckey As Integer = kvp.Key
articleIndex = kvp.Key 'save article key
Dim data As Artikel = kvp.Value

'-- If given article contains images list (artikel_images is a list with pictures associated with article)
If Not IsNothing(artikel.collection(articleIndex).ArtikelImages) Then
For Each img In artikel.collection(articleIndex).ArtikelImages
'--Insert article's images if exists
Using cmd As New SqlCommand("INSERT INTO T_Article_Image (Path, FK_Artikel_ID, Position) VALUES (@Path, @FK_Artikel_ID, @Position)", connection)
cmd.CommandType = CommandType.Text
cmd.Connection = connection
cmd.Transaction = transaction
cmd.Parameters.AddWithValue("@Path", img.Path)
cmd.Parameters.AddWithValue("@FK_Artikel_ID", newArticleRowId)
cmd.Parameters.AddWithValue("@Position", img.Position)
cmd.ExecuteScalar()
End Using
Next
End If

'-- If given article contains articles variations list (artikel_variation_attributes is a list with variations associated with article)
If Not IsNothing(artikel.collection(articleIndex)._artikel_variation_attributes) Then
For Each var In artikel.collection(articleIndex)._artikel_variation_attributes

'--Insert article's images if exists
Using cmd As New SqlCommand("INSERT INTO T_Artikel_T_Variation (FK_Variation_VariationAttribute_ID, FK_Artikel_ID, Position) VALUES (@FK_Variation_VariationAttribute_ID, @FK_Artikel_ID, @Position)", connection)
cmd.CommandType = CommandType.Text
cmd.Connection = connection
cmd.Transaction = transaction
cmd.Parameters.AddWithValue("@FK_Variation_VariationAttribute_ID", New Variation_VariationAttribute(var.FkVariationId, var.FkVariationAttributeId).GetId())
cmd.Parameters.AddWithValue("@FK_Artikel_ID", newArticleRowId)
cmd.Parameters.AddWithValue("@Position", var.Position)
cmd.ExecuteScalar()
End Using
Next
End If

Next
transaction.Commit()
Catch ex As Exception
result = False
'-- Roll the transaction back.
Try
transaction.Rollback()
Catch ex2 As Exception
result = False
End Try

End Try
End Using

Return result
End Function

Answer

I would not expect your catch to be reached. In your ProcessArticle function you have another Try .. Catch If there is an error in the SQL operation, this is where it will be caught. You then return false! So the calling routine does not catch the error, because it has already been handled gracefully. If you want to catch the error in your calling routine, then you will need to Raise an error from your catch in the ProcessArticle function.

You could change your Try Catch in ProcessArticle to

    Catch ex As Exception
        result = False
        '-- Roll the transaction back.
        Try
            transaction.Rollback()
        Catch ex2 As Exception
            Throw New Exception("Rollback failed after first exception.", ex2)
        End Try
        Throw New Exception("Rollback succeeded after exception.", ex)
    End Try

Sorry it's some time since I did VB, but I think the syntax is correct. Using this, the calling routine should now catch the Exception (and you will have an Exception with an inner exception). You will need to examine the inner exception to find the cause.

Comments