Setting a textbox property value within a catch block - vb.net

Using VS 2013 VB.net for my ClickOnce application. I've got a function which verifies database functionality and the guts are wrapped in a Try Catch. A portion of my Catch block looks like this:
Catch ex As Exception When Err.Number = "5"
My.Application.Log.WriteException(ex)
If My.Settings.g_blnDebugMode Then
MessageBox.Show(Err.Number & " " & ex.ToString, "Exception Error")
End If
If Err.Description.Contains("The specified table does not exist") Then
MessageBox.Show("Selected file is not a valid database.", "Exception Error")
ElseIf Err.Description.Contains("The specified password does not match the database password.") Then
MessageBox.Show("The specified password does not match the current database password.", "Exception Error")
End If
Return False
What I want to do is, clear two different fields based on the two custom error messages at the bottom. Something like TextBox1.Text = "" or TextBox2.Text = "" depending on which error is thrown (invalid password or invalid database). My problem is that I don't seem to be able to set them directly or set the value of a module or global variable from within the catch block.
Error is:
Cannot refer to an instance member of a class from within a shared method or shared member initializer without an explicit instance of the class.
If it's possible how can I work around this and set my TextBoxes based on the results in the Catch block?

Usually the method to achieve what you are trying is to use a second a catch block
Catch ex As Exception When Err.Number = ""
MessageBox.Show(ex.Message)
FlushTextBox1();
Catch ex As Exception When Err.Number = ""
MessageBox.Show(ex.Message)
FlushTextBox2();
The error is likely appearing because the try-catch block is inside a Shared method. What that means is, the change in the value of TextBox will be repeated for all instances of the class. If you want the TextBox to behave like this, add the Shared keyword to its own declaration and remove it from the Sub's declaration. If you don't want this behaviour at all, just remove the Shared keyword. For more information on the error check the MSDN article
Alternatively you can call a local function (as shown in code) FlushTextBox1() to change the value of the TextBox outside the Sub.

Related

Catch exception when using async/await and Task in VB.Net

I am parsing email from Outlook from vb.net. The main form displays the total count of mail for the selected Outlook folder and allows me to override this number so that I can process 1, 10, or all. When I click a button I open a new form passing in ref to my outlook mailClient class to provide access to the mail items. The form new and show events set up things and within a try/catch make a call to an async function like so.
Try
AllEMails = Await ScanMailItems(ref_clsEmailClient.ECFMailToScan,progressIndicator, tokenSource.Token)
Catch ag As AggregateException
If ag.InnerExceptions IsNot Nothing Then
MsgBox(ag.InnerExceptions.Count.ToString)
For Each ex In ag.InnerExceptions
MsgBox(ex.Message)
Next
End If
Catch ex As Exception
MsgBox(ex.Message & vbNewLine & vbNewLine & _
ex.StackTrace)
End Try
In this ScanMailItems() I am setting up a For Each Next to loop the mail items like so.
Dim EmailsFraction As Integer = Await Task(Of Integer).Run(
Function()
For i = ECFMailItems.Count To 1 Step -1
'other code
Throw New Exception("Test Error 1")
UpdateFormDelegate()
counter += 1
Next
Return counter
End Function)
Return EmailsFraction
The code this far is working and in the loop I am updating controls with some delegate subs to show subject and the email body of each email that will be parsed in the loop. My trouble is that I have placed some Throw New Exception("Test Error") in the for loop and in the delegate subs to be sure they will propagate back to my try/catch in my shown event. They do not and I have tried AggregateException. I can post actual code but think it is all in how the exception propagates through the async task.
I am just learning to do this, is there a better way to set it up? The main thing is that on each iteration of the For Loop my progress bar and the other controls need to update and I will be calling into other classes.

Is it possible to customize error message "Column does not allow nulls" in a datatable?

I have a form with controls bound to a datatable in VB.net.
When keeping empty a field that should be filled, I'm receiving the error message : Column does not allow nulls.
Is it possible to replace this error message string by another one ?
There are a lot of ways when it comes to error handling.
You could get your code to throw a custom error alert:
This will throw an alert with the text: NullCollumContent
Try
'your code here
Catch ex As Exception
Throw New System.Exception("NullCollomContent")
End Try
Also as K3rnel31 explained:
This will just show a simple message box to the user
Try
'your code here
Catch ex As Exception
msgbox("error message here")
End Try
You could also use If statements to check the string:
This if checks the length of the string and checks if its equal to 0:
If Not yourString.Length = 0 Then
'your code here
else
'some error handling here
End If
This if checks if your string is equal to "" which basically means an empty string:
If Not yourString Is "" Then
'your code here
Else
'some error handling here
End If
Try
'your code here to the datatable
Catch ex As Exception
msgbox("changed error string here")
End Try
Thank you all for your answers but that's not really my problem.
Everything is about DataTable Object.
My problem is that I don't know where the exception is raised.
Let me explain.
Assume Column X has AllowDBNull property to false
And I'm not creating manually a new row that I add to the table
Which means I'm not using such code:
Dim NewRow as DataRow = DataTable.NewRow
NewRom.Item("X") = textbox1.text
DataTable.rows.add(NewRow)
If I was using that code, I would have indeed added the Try/Catch
Dim NewRow as DataRow = DataTable.NewRow
NewRom.Item("X") = textbox1.text
try
DataTable.rows.add(NewRow)
catch Ex as Exception
...
end try
I'm using a DataNavigator which adds in a hidden manner the new row to be added to the table.
So, if Column X is empty, he raises by himself the error. It's not an Exception to be handled. It's an error displayed at run time. Programmatically speaking, nothing went wrong at run time. It seems like DataTable object is designed with this feature and default Error Message.
I hope it's clear now.

How to unit test KeyNotFoundException without assigning dictionary value

I wish to run a unit test on a particular dictionary in my code, trying to get a value I don't expect to be in the database (in this case, key=1).
I have written the following code:
Try
Dim s As String = myDict(1)
Catch ex As KeyNotFoundException
Assert.AreEqual("The given key was not present in the dictionary.", ex.Message)
Catch ex As Exception
Assert.Fail()
Throw
End Try
which works fine, but the code analysis is complaining about the "Dim s as String" declaration, as it says that s will never be used for anything. Well that's intentional, because I intend for this to throw an exception and s is irrelevant.
However, I can't seem to find a way to eliminate s from the code. Simply removing the assignment:
Try
myDict(1)
Catch ex As KeyNotFoundException
Assert.AreEqual("The given key was not present in the dictionary.", ex.Message)
Catch ex As Exception
Assert.Fail()
Throw
End Try
now fails to compile. Any suggestions on how to do this?
Unfortunately there is really no way to fix this in typed code. The call myDict(1) is an indexer and it's not legal as a statement (also illegal in C#). In order to test this you will need to use this expression as a part of legal statement.
One way to accomplish this is pass the value as a parameter to a method which doesn't use it
Sub Unused(ByVal o As Object)
End Sub
...
Unused(myDict(1))
if you are using NUnit Framework than
you could use the following code
Dim f As Func(Of Integer, String) = Function(i) myDict.Item(i)
Dim a As TestDelegate = Function() f(1)
Dim ex As KeyNotFoundException = Assert.Throws(Of KeyNotFoundException)(a)
Assert.AreEqual("The given key was not present in the dictionary.", ex.Message)
This is a similar solution which is proposed by JaredPar
Another option is to make the test returning a value and use the ExpectedException attribute so the code could look like this:
<TestCase(New Object(0 - 1) {}, Result:=Nothing), ExpectedException(GetType(KeyNotFoundException), ExpectedMessage:="The given key was not present in the dictionary."), Test> _
Public Function MyTest() As String
Return myDict.Item(1)
End Function
Looks like I can do this by putting a line after the dictionary call which uses the s variable:
Try
Dim s As String = theDocumentsWithUserNameDictDto.Dict(1)
Assert.Fail("Found unexpected value for dictionary key 1: " & s)
Catch ex As KeyNotFoundException
Assert.AreEqual("The given key was not present in the dictionary.", ex.Message)
End Try
I still don't expect the variable to be used (if the test passes), but this does have the benefit of providing extra clarity to the user if the test does fail for some reason.

How to continue insert if one row fails

I have a while loop where it fetches record from csv and inserts to sql table. Now csv may contain many rows.
What I want is if one row fails just log to a file and continue with next record. I was thinking of try and catch but that will exit the program. So, any suggestions?
while (csv.readnextline)
'assign csv columns to objects
try
'insert to db
Catch ex As Exception
'write to log file
End Try
I need the above code to continue after catching an exception.
Thanks
Try and catch do not exit the program, they just control the flow of the code in case something exceptional happens.
When an exception happens in the try block, the execution continues on the first line of the (corresponding) catch block. After the execution of the catch block, the code continues on the first line after the catch, which in your case could be the End While which will continue the loop.
So an construction like this
While dr.Read
Try
InsertRowIntoDataBase()
Catch ex As Exception
LogErrorToFile(ex)
End Try
End While
should work for you.
However, this is a bad design, as it will generate and log an exception, no matter what the problem is, whether the data is invalid, or the sql server is down, or even if there is an error in your code (e.g. some lurking NullReferenceException). You should limit the handling of exception to a specific case, e.g. to a problem with the database, like this:
While dr.Read
Try
InsertRowIntoDataBase()
Catch ex As SqlClient.SqlException
LogDataBaseErrorToFile(ex)
End Try
End While
Also, if there are known possible problems with the data (e.g. a string in the csv where an integer is expected) it's better to just check that than to use an exception mechanism, something along these lines:
While dr.Read
Try
If Not IsRowValid() Then
LogInvalidDataToFile()
Continue While
End If
InsertRowIntoDataBase()
Catch ex As SqlClient.SqlException
LogDataBaseErrorToFile()
Catch ex As Exception
LogGenericErrorToFile()
End Try
End While
no it won't exit the program, depending on how/where you handle the exception. If you do something like :
Dim WrongValuedLinesList As New List(Of String)
Dim ConversionFailedList As New List(Of String)
Dim InsertionFailedList As New List(Of String)
Dim NumberOfInsertedLines As integer = 0
For Each (CurrentLine in my csv)
' 1. line processing
Try
' (process my line : split, convert, check range...)
If (I know the insertion will fail) Then
' (Store information about that wrong line, in List, log, or do nothing)
WrongValuedLinesList.Add(" This line : " & CurrentLine
& " has wrong values because...
Continue For
End If
Catch ex as exception
' (here handle the line conversion failed : store in list, or log, or do nothing ...)
' for expl :
ConversionFailedList.Add(" Conversion failed for line " & CurrentLine
& " exception details : " & ex.message " )
End Try
' 2. Line insertion
Try
'(insert my processed data into database)
NumberOfInsertedLines +=1
Catch ex as exception
' (here handle the insertion failed exception (expl : primary key might not be unique)
' : store in list, log, do nothing...)
' for example :
InsertionFailedList.Add(" Insertion failed for line " & CurrentLine
& " exception details : " & ex.message " )
End Try
Next
(Here you might wanna report how things went to your user using
your error list.)

How do I migrate CanPropertyChange("Text") from VB6 to VB.NET?

I want to upgrade an ActiveX control from VB6 to VB.NET. I'm having trouble upgrading this code:
If CanPropertyChange("Text") Then
Text1.Text = Value
RaiseEvent TextChange()
End If
I get the error: "Name 'CanPropertyChange' is not declared."
VB.Net does not support anything similar to the CanPropertyChange("Text") method. The easiest way around this is to do the assignment within a Try...Catch block.
Try
Text1.Text = Value
RaiseEvent TextChange()
Catch ex As Exception
End Try
If the property cannot be written to an exception will be thrown which you can access in the Catch block.