Object Reference Error Using List.FindAll [duplicate] - vb.net

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 8 years ago.
I have a bizzare issue that I am struggling to resolve:
I have a form that performs a number of different searches using LINQ queries. 99% of the time the code will execute fine without any errors what so ever, however, on total random occasions, my form falls over on the following line:
'Find all tickets belonging to a user
Dim _userTicketsList As List(Of Ticket) = Tickets.FindAll(Function(p)
p.ticket_firstname.ToUpper = NewSearchString And
CDate(p.ticket_created_at.Value.ToShortDateString) >= date1
And CDate(p.ticket_created_at.Value.ToShortDateString) <= date2)
The error I get is Object Reference Not Set To An Instance Of An Object
From then on, any search will continue to bomb out on this line of code, until I restart my app. I execute the search again and everything works fine.
I cannot understand what is causing this error to occur. It can happen if .FindAll returns 0 results or if it returns any number of results.
Is there anyway I can determine what Object is trying to get set? I'm assuming its _userTicketsList but it doesn't make sense why sometimes it works and sometimes it doesn't.
I know it's probably hard to comment without seeing every bit of code, but is there anyway I can try and debug this differently? The debugger sits on this line of code for 23,000+ Ticket items, so I can't even work out if there is a specific Ticket that is causing the issue.
Any help or direction is greatly appreciated.
Thanks

Well, you can basically decorate your lambda expression with try catch statements, just to log / do something with the error.
'Find all tickets belonging to a user
Dim _userTicketsList As List(Of Ticket) = Tickets.
FindAll(Function(p)
Dim condition1 As Boolean
Dim condition2 As Boolean
Dim condition3 As Boolean
Try
condition1 = p.ticket_firstname.ToUpper = NewSearchString
Catch ex As Exception
'Do Something
End Try
Try
condition2 = CDate(p.ticket_created_at) >= date1
Catch ex As Exception
'Do Something
End Try
Try
condition3 = CDate(p.ticket_created_at) <= date2
Catch ex As Exception
'Do Something
End Try
Return condition1 And condition2 And condition3
End Function)
Code Addition Edited Per OP's comment
If _userTicketsList.Any = False Then
_userTicketsList = Nothing
End If
I also wanted to make sure you are aware of the difference in using And vs. AndAlso clause in vb.net.
When writing something like If(A and B)
both A and B will execute.
While using AndAlso, will not execute B if A is false,
since you are using And, I thought I'll mention it.

Related

How do I rollback a failed InsertOnSubmit? (VB.NET LINQ)

I'm having a problem with undoing a failed InsertOnSubmit when SubmitChanges fails. Here's the code:
Dim NewFac As New t_Facility With
{.FK_Instance_ID = guInstance_ID,
.FK_AccountType_ID = guAccountType_ID,
.FK_ATP_ID = guATP_ID,
.FK_Repayment_ID = guRepaymentType_ID,
.FK_InterestType_ID = guInterestType_ID,
.FK_FT_ID = guFacilitiesType_ID,
.NewRecord = bNewRecord,
.IndexNum = iIndexNum,
.SortCode = sSortCode,
.AccountNumber = sAccountNumber,
.Balance = decBalance,
.LastSanction = decLastSanctioned,
.Proposed = decProposed,
.Term_MTHs = iTerm_MTHS,
.Term_Expiry = dTerm_Expiry,
.InterestRate = decInterestRate,
.ArrangementFee = decArrangementFee,
.DateTime_From = Now(),
.ID = guFacilities_ID}
db.t_Facilities.InsertOnSubmit(NewFac)
Try
db.SubmitChanges()
Catch e As Exception
Console.WriteLine(e)
MessageBox.Show(e.Message & ". Please correct the field and try again", "ERROR", MessageBoxButton.OK, MessageBoxImage.Stop)
Exit Sub 'Takes the user back to the form to correct the value
End Try
When they hit submit again, it comes back around and fails at the same point with the same values as the original submission ignoring the new values that the user input.
The values in "NewFac" are the corrected new values. I've checked them on this line manually in debug: "db.t_Facilities.InsertOnSubmit(NewFac)"
I assume i need to somehow remove the failed "NewFac" that contains the incorrect values from "db.t_Facilities.InsertOnSubmit(NewFac)" in the catch somehow, but i don't see a way to do this?
FYI: I got the principal of this approach from here: https://msdn.microsoft.com/en-us/library/bb763516
Any help would be appreciated.
Now this is probably not going to be technically correct, so someone informed; please feel to give the real reason this worked (So its not really based on any statement of fact other than it worked, and is entirely my opinion - but it worked):
The solution dawned on me while reading through several questions from various other people having similar issues (all using various ways of Programmatically looping through the DataContext looking for a match), that the changes are just added the DataContext which appears to effectively act like an offline CLR of the database, so if InsertOnSubmit added to it, it stands to reason DeleteOnSubmit should remove it right?
So with that in mind, i tried this:
db.t_Facilities.InsertOnSubmit(NewFac)
Try
db.SubmitChanges()
Catch e As Exception
Console.WriteLine(e)
MessageBox.Show(e.Message & ". Please correct the field and try again", "ERROR", MessageBoxButton.OK, MessageBoxImage.Stop)
db.t_Facilities.DeleteOnSubmit(NewFac)
Exit Sub 'Takes the user back to the form to correct the value
End Try
It worked! :D
So i may be totally wrong as to why it worked (please inform me why - i'd genuinely like to know), but it worked.
EDIT:
If someone can give the correct reason it worked, i'll accept their answer instead of my own

If statement logic - read left to right?

I have an if statement in vb.net that reads something like this:
If String.IsNullOrEmpty(someDate) Or CDate(someDate) > DateTime.Now Then
'Do stuff here
End If
When someDate = Nothing, the app barfs. I could have sworn that these statements read left to right and as soon as it found a matching condition it would enter into the If code block.
I can write another statement that just does a null check. This results in no errors. Could someone clarify this?
They do go from left to right, the problem is you're using Or, which evaluates every condition. You need to use the short circuit version, OrElse:
If String.IsNullOrEmpty(someDate) OrElse CDate(someDate) > DateTime.Now Then
'Do stuff here
End If

What to return when a string function fails? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
Many of the applications I develop tap into the databases of pre-existing applications (I develop largely for small businesses that are trying to expand cheaply); A lot of this kind of work involves grabbing information out of other applications' databases (for example "site name", etc).
I normally have class libraries to do this kind of work, saving on database calls where possible. For example I might have a function like the below:
Private Function GetSiteName(ByVal dbPath As String) As String
Dim returned As String
Dim conn As New AdsConnection("data source = " & Path & "; ServerType=remote|local; TableType=CDX")
Dim cmd As AdsCommand
Try
conn.Open()
cmd = conn.CreateCommand()
cmd.CommandText = "select stSiteName from Sites;"
returned = cmd.ExecuteScalar
conn.Close()
Return returned
Catch e As AdsException
' write to log here
End Try
End Function
(For those not familiar, in the particular example above I'm accessing a database from Advantage Database Server).
In the above example, I would get a warning saying not all code paths return a value. If I move the Return statement to just before the End Function (outside the Try...Catch block, I would get a warning saying the variable may not be initialised.
Is there a standard/preferred way of handling this? At the moment I generally handle by putting the error message into the returned value, then testing for it from the calling code but it feels clunky to me.
The problem is that you handled the exception in your function. A handled exception is transparent to the caller, i.e. code outside this function will have no way of determining whether the exception was raised. This design is only correct when your function behaves correctly even when a exception is raised (hence can be handled).
When the catch statement is executed, the function does not know what value to return. That is the problem. You should not catch the exception at this level. You should let the exception raise, then past it to the upper level, where you can show appropriate error messages to the user.
The problem you are facing has nothing to do with Error Handling in particular. The compiler issues a warning if a function doesn't return something on all code paths, and you can choose it ignore it, since it is not categorized as an Error.
e.g. You will get the same warnings with If...Else if the code inside either If or Else doesn't return a value. Similarly you will get the warning in a Select..Case block if at least one of the Case blocks don't return a value.
It is however good to pay attention to what warnings the compiler issues and minimize the number of such warnings.
There are two approaches around this problem.
Keep multiple exit points in your function and ensure that all the exit points return some value.
Initialize your variable with some default value, and keep only one exit point for the function.
While it is debatable which one of the above is better, I personally like the second approach. It is better from code maintenance perspective too (when the function is too large).
For Example, you can initialize the variable with empty value or nothing to get rid of that warning.
Dim returned As String = String.Empty
...
Try
...
Catch e As AdsException
...
End Try
...
Return returned
In this example, you have 4 code paths from where the function can exit out (shown by ... in the example above). Assume that you had 10 or 15. You get a warning if you do not set the return value on any of the code paths. The above solution solves the problem by initializing the variable at the beginning, and return it at the end. Then you need not worry which code path sets the variable and which doesn't.

How do I use Do Until with a previous Try Catch Exception to avoid running the code twice

i have this line of code to catch an exception if a letter is inputed, or if it is out of rang as a number, but I have added WHEN to avoid catching numberical data. Now how can I use an exception error to use it before my case statement in order to avoid running the code twice, cause once the case codes has been through it will run a clear txtbox which is already taken care by the try catch, don`t if thats clear for you but i understand it. here is the code in parts...
Try
'Integer Levels: intLvls is egual to the assigned text box, the first one from
'the top, this line of code allow the user input to be captured into a variable.
intLvls = txtBoxLvl.Text
Catch ex As Exception When IsNumeric(intLvls)
ErrTypeLetterFeild1()
Finally
analysingvalues1()
End Try
WHAT I WOULD LIKE TO DO: Use loop until refencing the exception error to avoid running this following part of the code:
Private Sub analysingvalues1()
Do Until IsNumeric (ex As Exception)<------how do i do this???
Loop
the case part of the code:
Select Case intLvls
'User is prompt with the following label: lblLvl "Level of salespersons 1 - 4"
'to make a choice from 1 to 4 as available values.
Case 1 To 4
'This line regulates the range of acceptable values, first textbox: must be egual
'or higher than 1 and lower or egual to 4. Upon such rules a validation becomes
'correct and is directed to the isValidCalculation sub.
isValidCalculation()
Case Is < 1
ErrType1NumberRangeFeild()
Case Is > 4
ErrType1NumberRangeFeild()
Case Else
If txtBoxLvl.Text = "" Then
ErrTypeClear1()
Else
If Not IsNumeric(txtBoxLvl.Text) Then
ErrType1NumberRangeFeild()
Else
ErrTypeLetterFeild1()
ErrTypeClear1()
End If
End If
End Select 'Ending choices.
End Sub
Tks for your help!
If you turn on Option Strict this:
intLvls = txtBoxLvl.Text
Will no longer compile. This should tell you that your doing something smelly.
Turn on Option Strict
The correct solution is not to blindly allow the runtime to cast string to int for you, and catch the exceptions.
When you are converting string user input to an integer, bad input is not an exceptional condition, it is something you should expect and code defensively for.
I would rewrite it to something like this:
'Integer Levels: intLvls is egual to the assigned text box, the first one from
'the top, this line of code allow the user input to be captured into a variable.
if integer.TryParse( txtBoxLvl.Text, intLvls )
analysingvalues1()
else
ErrTypeLetterFeild1()
Edit - As pointed out by Chris below, I meant Option Strict. I recommend using but Explicit and Strict, and Infer if available.

why would I get a "is not declared. It may be inaccessible due to its protection level." only on the ELSE of an IF THEN ELSE block?

I am an utter newbie with VB.NET, so be gentle with my stupidity ;-)
I have a simple IF THEN ELSE block which checks for the presence of a querystring and then checks if it is set. The idea is that if no querystring, the form is empty and people can enter a new form. If there is a querystring and it isn't blank, a db query for the form data occurs, fields are populated and a user can update the form.
so here is my code block.
Dim strQueryStingCheck As String
If Not (Request.QueryString("pid") Is Nothing) Then ' is there a querystring?
If Request.QueryString("pid").ToString <> "" Then ' does it have a value?
strQueryStingCheck = "u"
Session("travelauthno") = Request.QueryString("pid")
Else
strQueryStringCheck = "e"
Session("travelauthno") = ""
End If
End If
I am getting the "Variable is not declared; it may be inaccessible due to its protection level" for strQueryStringCheck ONLY on the Else code block - that is when I set strQueryStringCheck to "e". I can't figure it out.
I've looked at other posts, particularly this one. and it was helpful. I can make the error go away, but I want to understand why I am getting it in the first place. I declared it within the subroutine. And if I was doing something wrong, shouldn't it throw an error on BOTH blocks of the IF THEN ELSE block? It doesn't when I set strQueryStringCheck to "u". Why only in the ELSE block?
PS I am coding in Visual Studio 2010. Also if I make it a simple IF...THEN...ELSE w/o nesting, the problem is still there.
That's because you have a typo in your IF branch. In if you have strQueryStingCheck, in else you have strQueryStringCheck. You are missing a r in the first one. You have the same typo in your variable declaration.
Look carefully ... Dim strQueryStingCheck As String
but in the else : strQueryStringCheck = "e"
Their is a R missing in your dim ...