Working with 1-Result-Linq with For Each? Any alternative? - vb.net

If I got a Linq-Query where I am knowing that it'll return 1 result only, like this:
Dim result = From g In Foo.Bar
Where g.keyID = 1
Select g
...do I still have to use the For Each loop to get the values or is there anything else I could use to work with 1-result-queries?
For Each x In result
TextBox1.Text = x.field1
TextBox2.Text = x.field2
TextBox3.Text = x.field3
Next

You can use Enumerable.First/ Enumerable.FirstOrDefault or Enumerable.Single/ Enumerable.SingleOrDefault(if it was exceptional if there were more than one).
Dim firstResult = result.FirstOrDefault()
If firstResult IsNot Nothing Then
TextBox1.Text = firstResult.field1
TextBox2.Text = firstResult.field2
TextBox3.Text = firstResult.field3
End If
So use First if it's possible that there are more than one but you want the first
Use Single if you want the first but it was a bug if there were more than one
The methods without OrDefault in the name will throw an exception if none was found
The OrDefault methods will return the default value(Nothing for reference types).

Related

Find line number in multiline textbox that contains certain data

I would need a little help.
Textbox1.Text contains 1,2,3,4,5,6,17.
Data in Textbox2:
Lines 0 = 1,2,3,4,5,7,18
Lines 1 = 21,2,3,4,5,7,19
Lines 2 = 13,11,3,4,5,7,19
Lines 3 = 1,2,3,4,5,6,17
Lines 4 = 1,2,3,4,5,6,21
How can I do?
For Each lines In Textbox2.Lines
Next
Expected Output: Textbox3.Text contains 3 (Because the combination from Textbox1 is found on the line 3 in the data).
Don't use for each.
You should iterate over your lines with an index and return the index.
Code exmaple:
For index As Integer = 0 To TextboxX.Lines.Length Step 1
' Here you can use your logic to check if the current line (by the index) is correct using TextboxX.Lines(index).
' Something like TextboxX.Lines(index) = Textbox1.text
If TextboxX.Lines(index) = Textbox1.Text Then
Textbox3.Text = index
Exit For
End If
Next
Bonus
This logic is already implemented in the framework, and it looks better like this:
Textbox3.Text = Array.IndexOf(TextboxX.Lines, Textbox1.Text)
Note - if the value was not found Array.IndexOf will return -1

Multiple string replace at one time

I have this string abcd, and I want to replace the a with [a|b] and the b with [c|d]
I try many ways to do it, like
Dim varString As String = "abcd"
varString = varString.Replace("a", "[a|b]")
varString = varString.Replace("b", "[c|d]")
The result I get is
[a|[c|d]][c|d]cd
Instead I want it like this
[a|b][c|d]cd
The problem is every time I use the replace function it backs to change the values I already replaced before so I replaced a with [a|b] but then when I do my second command to replace the b it changes the b in [a|b] that I just changed and I don't want this.
I tried to use StringBuilder but it gives the same result.
Please advise me,
I solved the problem by making an array in this way
Dim NewCommand As String = "abcd"
For i = 0 To LikeCommand.Length - 1
If LikeCommand(i) = "a" Then
NewCommand += "[a|b]"
ElseIf LikeCommand(i) = "b" Then
NewCommand += "[c|d]"
Else
NewCommand += LikeCommand(i)
End If
Next
LikeCommand = NewCommand
Or just switch the logic up. But obviously I'm thinking you're using a basic example for a more complex question.
dim varString as string = "abcd"
varString = varString.Replace("b" ,"[c|d]")
varString = varString.Replace("a" ,"[a|b]")
That would get you the desired results.

How can I add an Integer to a string and get a string answer?

I am using Visual Basic 2010.
I have tried several ways to try and add an integer to a string and then get the results as a string. Nothing I have tried seems to work. Below is the code I have at present time. Result is a label that I need to show the results after adding a 1 to the label result to get a new total. Can anyone help? Thanks!
Result.Text = CStr(CInt(Result.Text + 1))
You can not add numbers with a string. You need to first convert the string into an integer. You can do this like this:
Dim resultInteger = CInt(Result.Text)
You can then add resultInteger to 1 and set Result.text to the answer like this:
Result.Text = (resultInteger + 1).ToString
It, however, is possible to do this all on one line:
Result.Text = (CInt(Result.Text) + 1).ToString
Note that if Result.Text does not contain a number then it will crash you application. You could use a try statement like this:
Try
Result.Text = (CInt(Result.Text) + 1).ToString
Catch ex As Exception
msgbox("Result does not contain an integer!")
End Try
Result.Text = CStr(CInt(Result.Text) + 1)
Dim intResult As Integer = 0
If Integer.TryParse(Result.Text, intResult) Then
intResult += 1
Result.Text = intResult.ToString()
End If

Extracting the First (Oldest) Value from Dataset Based on Column Value

I don't have a great deal of experience working with DataSets and haven't been able to find the best way of achieving what I want to achieve.
I basically create a DataSet using a SQL Query and then I am trying to find a Specific Value in the 'Field' column and then if there is a 'Y' in the 'Flag' (as apposed to a 'N') Column on the same Row then I want it to change a check box's state to Checked as well as updating a labels text.
What I have seems to work however if no data is returned I get the below error:
Object reference not set to an instance of an object
If I change the code slightly from .FirstOrDefault() to .First() I get this error:
Sequence contains no elements
The part of the code that appears to be causing the problem is listed below. If you need to know anything else I will add it in.
Dim sSQL As String
sSQL =
<SQL>
SELECT MAX(UpdateTime) AS UpdateTime FROM AdminCS_Data_Current
WHERE UpdateUser = |##UpdateUser|
</SQL>
sSQL = Replace(sSQL, "##UpdateUser", AdminCB.Text)
Me.LastUserUpdate.Text = "Last Action: " & Format(ReturnDatabaseValue(sSQL, "UpdateTime", "Data"), "dd/MM/yyyy HH:mm:ss")
Dim EmployeeDataset As New DataSet
Try
sSQL =
<SQL>
SELECT * FROM AdminCS_Data_Current
WHERE UpdateUser = |##UpdateUser| AND CONVERT(DATE, UpdateTime) = CAST(GETDATE() AS DATE)
ORDER BY UpdateTime ASC
</SQL>
sSQL = Replace(sSQL, "##UpdateUser", AdminCB.Text)
EmployeeDataset = ReturnDataSet(sSQL, "Data")
If EmployeeDataset IsNot Nothing Then
Dim eData = EmployeeDataset.Tables(0)
If (eData.Select("Field = 'Timesheets Checked'").FirstOrDefault()("Flag")) IsNot Nothing Then
If eData.Select("Field = 'Timesheets Checked'").FirstOrDefault()("Flag").ToString.Trim = "Y" Then
TShtY.CheckState = CheckState.Checked
TShtTime.Text = Format(eData.Select("Field = 'Timesheets Checked'").First()("UpdateTime"), "HH:mm:ss")
Else
TShtN.CheckState = CheckState.Checked
End If
End If
' The above two IF statements would be repeated several times on each change of "Field"
End If
It would appear that this code has introduced not just iunefficiency but also a bug:
If (eData.Select("Field = 'Timesheets Checked'").FirstOrDefault()("Flag")) IsNot Nothing Then
If eData.Select("Field = 'Timesheets Checked'").FirstOrDefault()("Flag").ToString.Trim = "Y" Then
TShtY.CheckState = CheckState.Checked
TShtTime.Text = Format(eData.Select("Field = 'Timesheets Checked'").First()("UpdateTime"), "HH:mm:ss")
Else
TShtN.CheckState = CheckState.Checked
End If
End If
It should have been written like this in the first place:
Dim row = eData.Select("Field = 'Timesheets Checked'").FirstOrDefault()
If row IsNot Nothing Then
If row("Flag").ToString.Trim = "Y" Then
TShtY.CheckState = CheckState.Checked
TShtTime.Text = Format(row("UpdateTime"), "HH:mm:ss")
Else
TShtN.CheckState = CheckState.Checked
End If
End If
Easier to read, more efficient and avoids that nasty bug.
Also, I'd much rather see this:
Dim row = eData.Select("Field = 'Timesheets Checked'").FirstOrDefault()
If row IsNot Nothing Then
If row("Flag").ToString.Trim = "Y" Then
TShtY.Checked = True
TShtTime.Text = CDate(row("UpdateTime").ToString("HH:mm:ss")
Else
TShtN.Checked = True
End If
End If
You should never use the CheckState of a Checkbox unless it's tri-state, which maybe yours are but I doubt it. As for Format, we're not in VB6 anymore Toto.

Setting value to a not-existing array item?

Please take a look at the following code:
Try
Dim Reader As New System.IO.StreamReader(PositionsFileName)
Do While Reader.Peek() <> -1
Dim Positions() As String = Reader.ReadLine().Split("|")
If (Positions(0) Is Nothing) Or (Positions(1) Is Nothing) Or (Positions(2) Is Nothing) Then
' something
End If
Loop
Catch ex As Exception
ex.Source = Nothing
End Try
I am reading a file and expecting format something|something1|something2. I am trying to make it set "Nothing" to the array index which does not exists (the file format is broken), so that the If statement goes smoothly, but it seem I am doing it wrong. Can you give me some hints?
If you do Split("|") and there are only 2 items (for example, something|something1), Positions(2) will not be Nothing, it will just not be there. So your code will raise an exception, something about index out of bounds of the array.
If you need Positions(2) contain Nothing in this case, you code can look like this:
Dim Positions(2) As String
Dim tmpArray() As String = Reader.ReadLine().Split("|")
For i = 0 To UBound(Positions)
If i <= UBound(tmpArray) Then
Positions(i) = tmpArray(i)
Else
Positions(i) = Nothing
End If
Next
I assume that you only have three "Somethings" per valid line. If so, try writing your Positions() assignment like this:
Dim Positions() As String = Reader _
.ReadLine() _
.Split("|") _
.Concat(Enumerable.Repeat("Nothing", 3)) _
.Take(3) _
.ToArray()
This will ensure that you have three items every time. No need to check for nothings.
Just check positions.length after the split. Also, if you want to check for cases like "||Something2|Something3", the first position will be "" not Nothing. The orelse is a shortcircuit that will keep the latter condtitions from being evaulated if an earlier condition is met.
If Positions.length < 3 OrElse Positions(0) = "" OrElse Positions(1) = "" OrElse Positions(2) = "" Then
' something
End If