String assignment to dataview unexpectedly removes data row - vb.net

I'm stumped on a problem where VB is removing a row of data upon a simple string assignment. The processing loop is below. If the dvData dataview has 3 rows (i.e., dvData.Count is 3) then the string assignment below is causing the dataview to lose a row (i.e,. after executing the string assignment the dvData.Count is 2). What more odd is that this same string assignment call is used many other times in the same script without causing the loss of a data row.
For Each oneShipment As Shipment In DelShipmentsList
For intRow = 0 To (dvData.Count - 1)
' Example: if dvData.Count is 3 at this point, then....
dvData(intRow)("Result") = " Receipt Transaction Accepted."
' ... now dvData.Count will be 2!
Next
Next

Try examining your RowFilter property for that DataView object. If it's something like this, it would explain the issue:
dvData.RowFilter = "Result NOT LIKE '*Accepted*'"

It looks like we found the answer, albeit completely unforeseen and worthy of much head scratching. Just to be super sure about passing integers and strings explicitly, I had him us CStr() and CInt() where appropriate. Here's what we found:
' This string causes the dataview to change error
dvData(CInt(intRow))(CStr("Result")) = CStr("Receipt Transaction Accepted")
'This string does not.
dvData(CInt(intRow))(CStr("Result")) = CStr("Receipt Transaction Successful")
Apparently there’s something about the word "accepted". We spent quite a while trying different strings to figure out why the Specified string causes the odd behavior that remains otherwise unexplained.

Related

How to insert Listbox items in MS Access database in a single row

I have the following code:
Try
Dim queryString As String
queryString = "Insert into ServiceRecords([Personnel]) Values(#Personnels)"
command1 = New OleDbCommand(queryString, connection)
For i As Integer = 0 To Me.ListBox1.Items.Count + 1
command1.Parameters.AddWithValue("Personnels", ListBox1.Items(i))
command1.Parameters.Clear()
command1.ExecuteNonQuery()
Next
Catch ex As Exception
End Try
But I get the error below, and I don't know how to fix it. I think it happens because of my code.
And this is what I get:
Let's review.
First, as muffi suggested, use the Add method instead of .AddWithValue but instead of DBType use OLEDBType. There is not .String type in OleDBType. You will have to check your Access db to get the correct datatype. Probably VarChar. In addition, the parameter name should match the parameter name in your query string. With Access the position is the important thing but with other databases the name matters.
Second, as Charles suggested, change the plus one to minus 1. Most people start counting at one but computers usually start at zero so the upper index of the ListBox is one less than the Count (remember you are starting at zero not one).
Third , as Charles also pointed out it is wrong to clear the parameters before you execute. Then you would have nothing in your parameter. It is not necessary to clear them at all because you are overwriting the Value property with each iteration of your loop and I have set the name and datatype outside the loop because they stay the same. We don't want to reset properties for each iteration when they don't change.
command1.Parameters.Add("#Personnels", OleDbType.VarChar)
For i As Integer = 0 To ListBox1.Count -1
command1.Parameters("#Personnels").Value = ListBox1.Items(i)
command1.ExecuteNonQuery
Next

dr.Item("Value1") has value but always return 0 when assigned to another variable

I need to modify some VB.net code. There is a strange problem that I am facing. I am retrieving value from a DataTable and trying to assign it to a variable. When I check the value of some column in QuickWatch window then it has value but when I assign it to a variable then 0 is returned to the variable. Below is the simple statement that is causing the problem.
Dim MyAmount As Double = Double.Parse(dr.Item("Amount").ToString)
In the QuickWatch window when I check dr.Item("Amount") then it has value 30.12 and after executing the above statement MyAmount has value 0. May be VB.net work somewhat different that I do not know?
Edit:
It is kind of wierd that above mentioned statement is not returning value. The following statement is running absolutely fine.
Dim tmpVar As String() = dr.Item("Amount").ToString.Split(".")
Latest Edit:
I think it has become more wierd. The problem does not seem to be related with dr.Item("Amount"). Suppose I want to store the current culture value in a variable by following code,
Dim CultureInformation As String = System.Globalization.CultureInfo.CurrentCulture.DisplayName
Now CutlureInformation variable after the statement is executed contains "nothing" but the DisplayName has value of English (United States). So I think the problem is somewhere else.
You should be using this syntax:
Dim MyAmount As Double = dr.Field(Of Double)("Amount")
I am not sure why you are getting this behavior - your line should work too.
You can also try this:
Dim MyAmount As Double = DirectCast(dr.Item("Amount"), Double)
When facing a weird issue like this, always try various options to achieve the same result, do your research and compare the outputs. It greatly helps to answer a question on StackOverflow.

VB.NET - I'm curious, why does the return from "Right" not work as a string?

If I have a string like input = "AA["
If Right(input, 1) = "[" Then Do stuff
The If statement returns false, even if I try converting things around to chars, etc etc. But if I do this is returns true:
Dim temp As String = Right(input, 1)
If temp = "[" Then Do Stuff
I like knowing little semantics like this, any idea why it comes out this way?
Or don't use Right at all since this is .Net
Dim s As String = "AAAAAAA]"
If s.Substring(s.Length - 1, 1) = "]" Then
Stop
End If
'or
If s(s.Length - 1) = "]" Then
Stop
End If
I've seen weird behavior like that when debugging.
In fact, today I had something simlar
Dim records As Integer
records = If(o.dr Is Nothing, o.ADO.rs.RecordCount, o.ADO.DS.Tables("tbl").Rows.Count)
That should work, using the rs.RecordCount when dr is nothing, otherwise using the Rows.Count. It didn't, records was ending up as zero. Rewrote it as a full if then/else block and it works.
It's never my first thought that the compiler/debugger/ide is messing things up, but you should keep it in the back of your mind for consideration: the programmers that wrote those programs are just as human and fallible as you or me.
It shouldn't. Are you sure you didn't have a typo? The result of RIGHT is a string, and if the input was truly "AA[" the IF will have passed.
I've never had VB act wonky on something like this.
If the code appears in a form, then the .Right property of the form overrides the string manipulation function. You need to specify the parent namespace - e.g. VisualBasic.Right - to ensure that you get the correct method.
I think you may have some kind of strange overload confusion occuring here.
You are specifiing "Right" (which could be calling a local "Right" function).
The function your implying is "Microsoft.VisualBasic.Strings.Right" in most of my code ends up being "Strings.Right" due to the global import.
I would try changing you code to the below and see if it still happens, in order to rule out some overload/scope confusion. (and/or the reduced "Strings.Right")
If Micosoft.VisualBasic.Strings.Right(input, 1) = "[" Then Do stuff

VB.NET - Want to add together two nullable types - how? (i.e. var1 + var2 where both are nullable and vari1=Nothing, Var2=5 results in Nothing)

I have:
Dim nVar1 As Long?
Dim nVar2 As Long?
Dim nVarSum As Long?
nVar1 = Nothing
nVar2 = 5
nVarSum = nVar1 + nVar2
I would prefer the result to end with nVarSum being 5, instead of Nothing.
I understand if you add something to an unknown value, you will end up with "somthing + unknown" or
x+5 will always equal "x+5" not "5" because you are still carrying around that unknown "x".
However, how can I effectively treat an unknown or Nothing as a zero for the purposes of addition in this case?
Thanks!
(What is basically happening is that the end user is sending us a data file, this code parses that file and then sums together about 15 fields. If the user leaves those fields blank instead of assigning a zero to them, I need to treat it as if it was a zero for this one addition operation, but all the rest of the code needs to continue seeing it as a Nothing value since the user did not ACTUALLY submit zero... they submitted blank or nothing)
nVar1.GetValueOrDefault()+ nVar2.GetValueOrDefault()
Or in c#:
(nVar1??0)+(nVar2??0)
I think the simplest way is to use the If operator to coerce Nothing values into a default one.
nVarSum = If(nVar1,0) + If(nVar2,0)
The If operator in the 2 argument form when applied to nullable types essentially does the following. If the nullable has a value then the return is the value, otherwise it's the second argument.
Or explicitly test for nothing and set your default value. Same result as other answers posted.
If nVar1 is nothing then
nVar1 = 0
end if
nVarSum = nVar1 + nVar2

ComboBox DataBinding DisplayMember and LINQ queries

Update
I decided to iterate through the Data.DataTable and trimmed the values there.
Utilizing SirDemon's post, I have updated the code a little bit:
Sub test(ByVal path As String)
Dim oData As GSDataObject = GetDataObj(path)
EmptyComboBoxes()
Dim oDT As New Data.DataTable
Try
Dim t = From r In oData.GetTable(String.Format("SELECT * FROM {0}gsobj\paths ORDER BY keyid", AddBS(path))) Select r
If t.Count > 0 Then
oDT = t.CopyToDataTable
For Each dr As Data.DataRow In oDT.Rows
dr.Item("key_code") = dr.Item("key_code").ToString.Trim
dr.Item("descript") = dr.Item("descript").ToString.Trim
Next
dataPathComboBox.DataSource = oDT
dataPathComboBox.DisplayMember = "descript"
dataPathComboBox.ValueMember = "key_code"
dataPathComboBox.SelectedIndex = 0
dataPathComboBox.Enabled = True
End If
Catch ex As Exception
End Try
End Sub
This works almost as I need it to, the data is originally from a foxpro table, so the strings it returns are <value> plus (<Field>.maxlength-<value>.length) of trailing whitespace characters. For example, a field with a 12 character length has a value of bob. When I query the database, I get "bob_________", where _ is a space.
I have tried a couple of different things to get rid of the whitespace such as:
dataPathComboBox.DisplayMember.Trim()
dataPathComboBox.DisplayMember = "descript".Trim.
But nothing has worked yet. Other than iterating through the Data.DataTable or creating a custom CopyToDataTable method, is there any way I can trim the values? Perhaps it can be done in-line with the LINQ query?
Here is the code I have so far, I have no problem querying the database and getting the information, but I cannot figure out how to display the proper text in the ComboBox list. I always get System.Data.DataRow :
Try
Dim t = From r In oData.GetTable("SELECT * FROM ../gsobj/paths ORDER BY keyid") _
Select r
dataPathComboBox.DataSource = t.ToList
dataPathComboBox.SelectedIndex = 0
'dataPathComboBox.DisplayMember = t.ToList.First.Item("descript")
dataPathComboBox.Enabled = True
Catch ex As Exception
Stop
End Try
I know that on the DisplayMember line the .First.Item() part is wrong, I just wanted to show what row I am trying to designate as the DisplayMember.
I'm pretty sure your code tries to set an entire DataRow to a property that is simply the name of the Field (in a strongly type class) or a Column (in a DataTable).
dataPathComboBox.DisplayMember = "descript"
Should work if the DataTable contains a retrieved column of that name.
Also, I'd suggest setting your SelectedIndex only AFTER you've done the DataBinding and you know you actually have items, otherwise SelectedIndex = 0 may throw an exception.
EDIT: Trimming the name of the bound column will trim just that, not the actual bound value string. You either have to go through all the items after they've been bound and do something like:
dataPathComboBox.Item[i].Text = dataPathComboBox.Item[i].Text.Trim()
For each one of the items. Not sure what ComboBox control you're using, so the item collection name might be something else.
Another solution is doing that for each item when it is bound if the ComboBox control exposes an onItemDataBound event of some kind.
There are plenty of other ways to do this, depending on what the control itself offers and what you choose to do.
DisplayMember is intended to indicate the name of the property holding the value to be displayed.
In your case, I'm not sure what the syntax will by since you seem to be using a DataSet, but that should be
... DisplayMember="Item['descript']" ...
in Xaml, unless you need to switch that at runtime in which case you can do it in code with
dataPathComboBox.DisplayMember = "Item['descript']"
Again, not 100% sure on the syntax. If you are using a strongly typed DataSet it's even easier since you should have a "descript" property on your row, but given hat your error indicates "System.DataRow" and not a custom type, I guess you are not.
Because I can't figure out the underlying type of the datasource you are using I suggest you to change commented string to
dataPathComboBox.DisplayMember = t.ElementType.GetProperties.GetValue(0).Name
and try to determine correct index (initially it is zero) in practice.