VB.net Strange Conditional Statement (IF) - vb.net

Was wondering if someone could lend me their expertise. Pretty new to Vb.net and have come across this conditional statement in one of our products. Could someone please confirm the validity of the statement and explain what's going on here? I've tried numerous searches, but I cannot find anything related.
If (IsDBNull(dr("someID")), "0", dr("someID")) = someID.ToString() Then
I have changed the "id" value names as it's code from a commercial product, but the ID's used were all the same variable (ints).
Thanks for any input you can offer on this!
Joe
PS: The reason I can't check this at run time is because of how the product operates.

It is an inline If statement
If(condition,iftrue,iffalse) if condition is true evaluate and return iftrue else iffalse

The If operator in VB.NET 2008 acts as a ternary operator.[ REFERENCE]
Example:
Dim foo as String = If(bar = buz, cat, dog) 'Condition satisfied then it'll return cat else dog.

The statement is checking to see if the dr("SomeID") equals the value someID.ToString. The reason the If is required is because you need to check if the dr("someID") Is Null. If it is 0 is used instead which presumably should not be equal to someID.
It is the same as doing the following:
If Not IsDBNull(dr("someID")) Then
If dr("someID").ToString = someID.ToString Then
End If
End If
I would suggest that something like this would be more appropriate (checking integer values instead of comparing strings)
If(IsDBNull(dr("someID")), 0, CInt(dr("someID"))) = someID Then
I would also suggest Turning Option Strict On as the code you posted should not compile!

Related

Use String for IF statement conditions

I'm hoping someone can help answer my question, perhaps with an idea of where to go or whether what I'm trying to do is not possible with the way I want to do it.
I've been asked to write a set of rules based on the data held by our ERP form components or variables.
Unfortunately, these components and variables cannot be accessed or used outside of the ERP, so I can't use SQL to query the values and then build some kind of SQL query.
They'd like the ability to put statements like these:
C(MyComponentName) = C(MyOtherComponentName)
V(MyVariableName) > 16
(C(MyComponentName) = "") AND V(MyVariableName) <> "")
((C(MyComponentName) = "") OR C(MyOtherComponentName) = "") AND V(MyVariableName) <> "")
This should be turned into some kind of query which gets the value of MyComponentName and MyOtherComponentName and (in this case) compares them for equality.
They don't necessarily want to just compare for equality, but to be able to determine whether a component / variable value is greaterthan or lessthan etc.
Basically it's a free-form statement that gets converted into something similar to an IF statement.
I've tried this:
Sub TestCondition()
Dim Condition as string = String.Format("{0} = {1}", _
Component("MyComponent").Value, Component("MyOtherComponent").Value)
If (Condition) Then
' Do Something
Else
' Do Something Else
End If
End Sub
Obviously, this does not work and I honestly didn't think it would be so simple.
Ignoring the fact that I'd have to parse the line, extract the required operators, the values from components or variables (denoted by a C or V) - how can I do this?
I've looked at Expression Trees but these were confusing, especially as I'd never heard of them, let alone used them. (Is it possible to create an expression tree for dynamic if statements? - This link provided some detail on expression trees in C#)
I know an easier way to solve this might be to simply populate the form with a multitude of drop-down lists, so users pick what they want from lists or fill in a text box for a specific search criteria.
This wouldn't be a simple matter as the ERP doesn't allow you to dynamically create controls on its forms. You have to drag each component manually and would be next to useless as we'd potentially want at least 1 rule for every form we have (100+).
I'm either looking for someone to say you cannot do this the way you want to do it (with a suitable reason or suggestion as to how I could do it) that I can take to my manager or some hints, perhaps a link or 2 pointing me in the right direction.
If (Condition) Then
This is not possible. There is no way to treat data stored in a string as code. While the above statement is valid, it won't and can't function the way you want it to. Instead, Condition will be evaluated as what it is: a string. (Anything that doesn't boil down to 0 is treated as True; see this question.)
What you are attempting borders on allowing the user to type code dynamically to get a result. I won't say this is impossible per se in VB.Net, but it is incredibly ambitious.
Instead, I would suggest clearly defining what your application can and can't do. Enumerate the operators your code will allow and build code to support each directly. For example:
Public Function TestCondition(value1 As Object, value2 As Object, op as string) As Boolean
Select Case op
Case "="
Return value1 = value2
Case "<"
Return value1 < value2
Case ">"
Return value1 > value2
Case Else
'Error handling
End Select
End Function
Obviously you would need to tailor the above to the types of variables you will be handling and your other specific needs, but this approach should give you a workable solution.
For my particular requirements, using the NCalc library has enabled me to do most of what I was looking to do. Easy to work with and the documentation is quite extensive - lots of examples too.

Regex match SQL values string with multiple rows and same number of columns

I tried to match the sql values string (0),(5),(12),... or (0,11),(122,33),(4,51),... or (0,121,12),(31,4,5),(26,227,38),... and so on with the regular expression
\(\s*\d+\s*(\s*,\s*\d+\s*)*\)(\s*,\s*\(\s*\d+\s*(\s*,\s*\d+\s*)*\))*
and it works. But...
How can I ensure that the regex does not match a values string like (0,12),(1,2,3),(56,7) with different number of columns?
Thanks in advance...
As i mentioned in comment to the question, the best way to check if input string is valid: contains the same count of numbers between brackets, is to use client side programm, but not clear SQL.
Implementation:
List<string> s = new List<string>(){
"(0),(5),(12)", "(0,11),(122,33),(4,51)",
"(0,121,12),(31,4,5),(26,227,38)","(0,12),(1,2,3),(56,7)"};
var qry = s.Select(a=>new
{
orig = a,
newst = a.Split(new string[]{"),(", "(", ")"},
StringSplitOptions.RemoveEmptyEntries)
})
.Select(a=>new
{
orig = a.orig,
isValid = (a.newst
.Sum(b=>b.Split(new char[]{','},
StringSplitOptions.RemoveEmptyEntries).Count()) %
a.newst.Count()) ==0
});
Result:
orig isValid
(0),(5),(12) True
(0,11),(122,33),(4,51) True
(0,121,12),(31,4,5),(26,227,38) True
(0,12),(1,2,3),(56,7) False
Note: The second Select statement gets the modulo of sum of comma instances and the count of items in string array returned by Split function. If the result isn't equal to zero, it means that input string is invalid.
I strongly believe there's a simplest way to achieve that, but - at this moment - i don't know how ;)
:(
Unless you add some more constraints, I don't think you can solve this problem only with regular expressions.
It isn't able to solve all of your string problems, just as it cannot be used to check that the opening and closing of brackets (like "((())()(()(())))") is invalid. That's a more complicated issue.
That's what I learnt in class :P If someone knows a way then that'd be sweet!
I'm sorry, I spent a bit of time looking into how we could turn this string into an array and do more work to it with SQL but built in functionality is lacking and the solution would end up being very hacky.
I'd recommend trying to handle this situation differently as large scale string computation isn't the best way to go if your database is to gradually fill up.
A combination of client and serverside validation can be used to help prevent bad data (like the ones with more numbers) from getting into the database.
If you need to keep those numbers then you could rework your schema to include some metadata which you can use in your queries, like how many numbers there are and whether it all matches nicely. This information can be computed inexpensively from your server and provided to the database.
Good luck!

When does = perform comparison instead of assignment?

In VB.NET, there's no == operator for comparison, so the = operator serves that purpose as well as assignment. I have a function, and I want it to return the boolean result of a comparison, without storing that result in a variable:
Private Function foo() As Boolean
Dim bar As Integer = 1
Return bar = 2
End Function
Returns: False
OK, but what's the value of bar?
Private Function foo() As KeyValuePair(Of Boolean, Integer)
Dim bar As Integer = 1
Return New KeyValuePair(Of Boolean, Integer)(bar = 2, bar)
End Function
Returns: False, 1
It looks like = will perform a comparison when the statement context demands it, but is this guaranteed? That is, can I be sure that bar will never be set to 2 in this situation?
Also, I know that VB.NET doesn't allow chained inline assignments, which may be for the best. Does this odd = behavior cause any other quirks I should be aware of?
You cannot do in-line assignments in VB, Assignment is an explicit statement:
[Let] <<target-reference>> = <<value-expression>>
The Let is optional and implicit, and hardly ever used anymore. The general rule that you can use to distinguish the [Let] command from equality testing is that for Let, no other keyword may come before the target-reference in the statement. AFAIK, in all cases of = as equality testing, there is one or more other keywords that precede it in the statement.
In your first example, the keyword Return precedes your =, so it's an equality test, and not an assignment.
In your first example you can do either:
Return 2
or
bar = 2
Return bar
As for your question "OK, but what's the value of bar?", bar still equals one.
= in VB cause no quirks. It works exactly as documented, and it always has (including its predecessor, BASIC back to 1968).
If you are starting to code in VB (coming from a language like C#), you should start getting used to the peculiar VB way of doing things; which is based on the idea: as simple and intuitive for the programmer as possible. "If assignation and comparison happen always in different contexts, why not using the same operator and let the context define its exact meaning?" -> VB-way of seeing things. "No, different realities have to be accounted for by different operators. End of the discussion" -> C#-way. :)
Is this reliable? Can you blindly trust on these not-always-clear-for-a-programmer bits? Sure, VB.NET peculiarities are highly-reliable and trustworthy. You can always use = (or Is on some contexts, but VS would tell you) and be completely sure that the code will do what is expected. But the question is: are you sure that you write exactly what you want?
This last question is what, perhaps, is more criticable of VB and what might give some problems to programmers from other languages: the higher the flexibility, the more likely is that you make an error; mainly if you are used to a different format.
Regarding the chained inline assignments, I honestly don't see its true utility (and never use them in C#). Regarding other differences with respect to C#, there are plenty of them; in some cases, I think that the C# approach is better; other times, the VB.NET one. On readability/length of code, I can refer to the With Statement I have always found somehow useful which is not present in C#.
One way to have 100% sure that the expression will be evaluated as an boolean expression is to use ()
e.g
Dim a = 2
Return (a = 1)
Since you cannot set a value to a variable wihtin the parenthesis.
What i want to say is: on an return statament for example you cant assing a value to a variable so, even if you use
a = 1
The compilator knows that this expression only can be an boolean expression.
The same to the if statament and so on..
Heh back in QB45 days we used to exploit the fact that "True" was the numeric value -1. So you would see code like x = 1 - x * (x < 6) (translation: increment x, but reset to 1 when it gets to 6)

Reporting Services - handling an empty date?

Hey, I have a report parameter which looks like this: 01.01.2009 00:00:00
Its a date (as string), as you might have guessed :). The problem is, this param can be an empty string as well. So I tried those expressions:
=IIf(IsDate(Parameters!DateTo.Value), CDate(Parameters!DateTo.Value), "")
=IIf(Len(Parameters!DateTo.Value) > 0, CDate(Parameters!DateTo.Value), "")
Both dont work and the value for the textfield where I print the expressions result is always #Error. As soon as I remove the CDate stuff, it works, but I have to use it. IS there another way to achieve that? What I want is to display nothing if its not a date or the date (format dd.mm.yyyy) if its a date.
Ideas?
Thanks :)
All arguments to the IIf are evaluated, which results in your error, since the CDate will fail for an empty string.
You can get around this by just writting a function along these lines, using a standard if statement:
Function FormatDate(ByVal s As String) As String
If (s <> "") Then
Return CDate(s).ToString()
Else
Return ""
End If
End Function
Then call it with: =Code.FormatDate(Parameters!DateTo.Value)
First, fix your database to properly store dates rather than doing these workarounds. You probably have bad data in there as well (Feb 30 2010 for example or my favorite, ASAP). Truly there is no excuse for not fixing this at the database level where it needs to be fixed except if this is vendor provided software that you can't change (I would yell at them though, well notify them really, and ask them to fix their data model or go to a new product designed by someone who knows what they are doing. A vendor who can't use dates properly is likely to have software that is very poor all around).
In the query that you use to select the infomation, have you considered just converting all non-dates to null?

Newbie issue with LINQ in vb.net

Here is the single line from one of my functions to test if any objects in my array have a given property with a matching value
Return ((From tag In DataCache.Tags Where (tag.FldTag = strtagname) Select tag).Count = 1)
WHERE....
DataCache.Tags is an array of custom objects
strtagname = "brazil"
and brazil is definitely a tag name stored within one of the custom objects in the array.
However the function continually returns false.
Can someone confirm to me that the above should or should not work.
and if it wont work can someone tell me the best way to test if any of the objects in the array contain a property with a specific value.
I suppose in summary I am looking for the equivalent of a SQL EXISTS statement.
Many thanks in hope.
Your code is currently checking whether the count is exactly one.
The equivalent of EXISTS in LINQ is Any. You want something like:
Return DataCache.Tags.Any(Function(tag) tag.FldTag = strtagname)
(Miraculously it looks like that syntax may be about right... it looks like the docs examples...)
Many Thanks for the response.
Your code did not work. Then I realised that I was comparing to an array value so it would be case sensitive.
However glad I asked the question, as I found a better way than mine.
Many thanks again !