Most of our development is done in vb.net (not my choice) and one frequently used code pattern uses an \'On Error GoTo\' followed by a \'Resume Next\' so that all database f
Use the IsDbNull
method to check for null values instead of a costly try-fail-handlefailure approach. Error handling is almost always more expensive than catching a condition before it becomes an error.
(Also, error handling should use exceptions, not VB6-style ON ERROR GOTO HELL...)
With the conditional If
function that would look like this as a one-liner:
oObject.Name = If(oReader.IsDbNull(oReader.GetOrdinal("Name")), Nothing, oReader.GetString(oReader.GetOrdinal("Name")))
I would prefer to write some helper functions that could be used to make the code more readable and more efficient:
Function GetStringOrDefault(reader As DbDataReader, key As String) As String
Dim ordinal = reader.GetOrdinal(key)
If reader.IsDbNull(ordinal) Then
Return Nothing
Else
Return reader.GetString(ordinal)
End If
End Function
Usage:
oObject.Name = GetStringOrDefault(oReader, "Name")
You could alternatively write them as extensions to the DbDataReader
class to make them even more readable.
In VB 9.0, "IF" is a true coalescing operation equivalent to C#'s "??". Source MSDN:
So you could use:
oObject.Name = IF(oReader.Item("Name").Equals(DBNull.Value),string.Empty,DirectCast(oReader.Item("Name"), String))
Everyone has added some valid points to this discussion so I thought I'd summarise the important points.
VB.net TryCast() is NOT the same as the C# as keyword. If it was the same then there would have been no need for this question in the first place.
VB.net uses the If() function for ternary operations and null coalescing operations. This is not as easy to read as the C# version (? and ?? respectivly). Try to avoid the vb.net IIf() function as this is not the same.
The null coalescing code pattern does not work as we cannot use the TryCast() with nullable types so we have to use the terniary pattern.
oReader.IsDBNull(oReader.GetOrdinal("Name")) is the best way to check if a value is DBNull.
Sorry for sprouting such nonsense. I relied on a posting by Paul Vick (then head of the VB team) rather than the MSDN and don't have Windows installed to test the code.
I'll still leave my posting – heavily modified (refer to the edit history to read the wrong original text) – because I find the points still have some merit.
So, once again, three things to recap:
For reference types, C#'s as
is directly modelled by TryCast
in VB.
However, C# adds a little extra for the handling of value types via unboxing (namely the possibilities to unbox value types to their Nullable
counterpart via as
).
VB 9 provides the If
operator to implement two distinct C# operators: null
coalescing (??
) and conditional (?:
), as follows:
' Null coalescing: '
Dim result = If(value_or_null, default_value)
' Conditional operator: '
Dim result = If(condition, true_value, false_value)
Unlike the previous IIf
function these are real short-circuited operators, i.e. only the necessary part will be executed. In particular, the following code will compile and run just fine (it wouldn't, with the IIf
function, since we could divide by zero):
Dim divisor = Integer.Parse(Console.ReadLine())
Dim result = If(divisor = 0, -1, 1 \ divisor)
On Error GoTo …
or On Error Resume [Next]
). That's backwards compatibility stuff for easy VB6 conversion. Instead, use .NET's exception handling mechanisms like you would in C#.I don't think that VB.NET has any operator that mimics the functioning of the ??
operator of C#. However, you could use the equivalent of C#'s ternary operator - The IIF function in your case:
Admittedly ugly:
oObject.Name = IIf(oReader.Item("Name").Equals(DBNull.Value), DirectCast(oReader.Item("Name"), String), String.Empty)
oObject.Value = IIf(oReader.Item("Value").Equals(DBNull.Value), DirectCast(oReader.Item("Value"), Integer), -1)
Please make sure to read Stephen Weatherford's post in the link I provided above which suggests a generic IIf function that infers type requirements from the provided arguments. This becomes necessary because the IIf function always returns an Object!
A better option would be to create a function that performs this cast conditionally, rather than trying to do it in one line.
According to the docs TryCast only works with reference types. Regardless, the problem might be more with your usage of the IDataReader than trycast.
Before looping over the rows in the IDataReader, get the ordinal values of the column names and use the strongly typed GetX methods to retrieve the field values like so
Dim name As Integer = oReader.GetOrdinal("Name")
Dim value as Integer = oReader.GetOrdinal("Value")
While reader.Read()
oObject.Name = if(oReader.IsDbNull(name), string.Empty, oReader.GetString(name))
oObject.Value = if(oReader.IsDbNull(value), -1, oReader.GetInt32(value)
End While
' Call Close when done reading.
oReader.Close()
Using the if operator with 3 parameters like so makes it work like the C# ternary boolean operator eval?trueExpression:falseExpression
This should help you with your issue.