DbNull.Value and isDBNull for datacolumn - asp.net

I have a DataRow which contain data from database. I want to check each data column for Null value in an IF condition.
I found two ways to check NULL value.
If IsDBNull(drType("ISShort")) Then
StartDate.Visible = True
Else
StartDate.Visible = False
End If
and
If Not drType("ISShort").ToString Is DBNull.Value Then
StartDate.Visible = True
Else
StartDate.Visible = False
End If
Both works fine for me but I don't know which one is better to use ?

I prefer DataRow.IsNull which returns a bool, is readable and efficient:
StartDate.Visible = drType.IsNull("ISShort")
related: Which of IsDBNull and IsNull should be used?
Note that your second approach doesn't work. If you convert it to String with ToString it can't be DBNull.Value. That compiles only with option-strict set to off which i strongly advise against.

Second case makes no sense as it does unnecessary ToString().
Note, there is another way you can use DbNull
If DbNull.Value.Equals(row.Item(fieldName)) Then
...
you can also use myDataRow.IsNull(fieldName) which is faster according to Which of IsDBNull and IsNull should be used?

Related

ASP Session variables: Is "" same as IsEmpty?

In ASP an uninitialized Session variable Is Empty. I know that the correct way to check for a Session value, and remove a value, is the following:
IF NOT IsEmpty(Session("myVar")) THEN
' Go ahead and use Session("myVar")
...
' Now if we're all done with myVar then remove it:
Session.Contents.Remove("myVar")
END IF
I've inherited a codebase where Application and Session variables are typically set = "" after use, and all tests for a value are of the form (Sessions("myVar") = ""). This test appears to work when the Session variable has not been declared ... or maybe it's just working by dumb luck.
Is it safe to use comparison with the empty string to test for a Session variable? I.e., is the following "practically as good" as the correct method shown above?
IF Session("myVar") <> "" THEN
' Go ahead and use Session("myVar")
...
' Now if we're all done with myVar then blank it:
Session("myVar") = ""
END IF
Or should I refactor the codebase so that:
All tests to determine whether a Session variable has been set are of the form IsEmpty(Session("myVar"))
All session variables are Removed and not set = ""?
Empty is a strange beast: it is simultaneously equal to both "" and 0. Seriously, try it:
dim x, y, z
x = Empty
y = ""
z = 0
Response.Write (x = y) AND (x = z)
It'll write out "True".
This means that testing for Not IsEmpty(myvar) is equivalent to testing myvar <> "", but IsEmpty(myvar) is not equivalent to myvar = "". Whether that mostly-theoretical difference bothers you or not is something only you can answer, but personally, I wouldn't waste time on refactoring.
If you do decide to refactor, I would suggest forgetting about IsEmpty and IsNull and whatnot, and just using the & "" "hack":
If Session("myvar") & "" <> "" Then
This'll transparently handle Nulls and Empties without you needing to write a whole bunch of code.
No, it could be not safe. Perhaps you need to use functions: IsNull, IsEmpty and VarType
IsNull -- returns True if expression is Null, that is, it contains no
valid data; otherwise, IsNull returns False. If expression consists of
more than one variable, Null in any constituent variable causes True
to be returned for the entire expression.
VarType -- Returns a value indicating the subtype of a variable.
IsEmpty -- returns True if the variable is uninitialized, or is
explicitly set to Empty; otherwise, it returns False. False is always
returned if expression contains more than one variable.
Please take a look at What is the '<>' asp operator?

How to really check if something is null in VB.NET?

I have an entity with a NrPeso decimal property that can be saved in the database as 0 or null.
Here is what I'm doing to assign the value to the property:
entity.NrPeso = Convert.ToDecimal(object.value("value"))
The problem is: if I don't fill the object value, it's set to Nothing. When I do the cast it turns into 0. But I don't want 0, I want Nothing. If I compare the object value with Nothing it will return me Nothing if it is Nothing or 0.
I tought in a few alternatives but they don't seem good.
So, what is the right way to do this?
Decimal is a structure - is cannot be Nothing by definition.
You need a nullable Decimal.
If NrPeso is defined as Nullable(Of Decimal) (aka Decimal?), things should work as you expect.
If you want to distinguish between 0 and Nothing when using Decimal (or any other value type), you should use a nullable type in the first place.
So use Decimal? instead of Decimal
Try this:
Dim obj As Object = object.value("value")
entity.NrPeso = If (obj Is Nothing, Nothing, Convert.ToDecimal (obj))
Instead of using Convert.ToDecimal, consider using Decimal.TryParse and then in a failure condition explicitly set the Nullable type to Null:
Dim outVal As Decimal?
If Decimal.TryParse(object.value("value"), outVal)
entity.NrPeso = outVal
Else
entity.NrPeso = Nothing
End If
Additionally, consider setting Option Strict On in your project to avoid type issues like this in the future.

Why won't this work as an IIF function, but will as an IF Statement?

The following works:
If 1=1
rdoYes.checked = True
Else
rdoNo.checked = True
End If
However, the following doesn't work:
IIF(1=1, rdoYes.checked = True, rdoNo.checked = True)
Why is this?
Thanks!
It does "work"; it just doesn't do what you want.
IIf in VB.NET is a function (don't use it, ever, by the way), which takes these parameters:
A Boolean condition to check
An Object to return if the condition is True
A different Object to return if the condition is False
In your usage, your condition is 1 = 1; then your two other parameters are rdoYes.Checked = True and rdoNo.Checked = True, both Boolean expressions from the VB compiler's perspective (so, really, they're equivalent to the simpler rdoYes.Checked and rdoNo.Checked).
Remember that in VB.NET, the = sign is only an assignment if it is on its own line. This is how the compiler distinguishes between statements such as x = 5 and If x = 5 Then.
This is not directly related to your question, but you should also be aware that IIf is deprecated and you should almost always favor If instead:
' Let us just suppose it made sense to write this: '
' Notice the If instead of IIf. '
Dim result = If(1 = 1, rdoYes.Checked, rdoNo.Checked)
The IIF() function will return something based on what you enter for the first parameter. Since VB.Net doesn't differ between = as in assignment and = as in comparison (== in many other languages), the second statement is ambiguous.
You can do this with using late binding (delegates in VB.Net):
(Function(c) InlineAssignHelper(c.Checked, true)).Invoke(IIf(1 = 1, chkYes, chkNo))
Private Function InlineAssignHelper(Of T)(ByRef target As T, ByVal value As T) As T
target = value
Return value
End Function
Because IIf takes expressions and returns a result of one of them, and rdoYes.checked = True is not an expression and cannot be returned.
iif doesn't do what you think it does -- the important part is the return from it, so you might be able to do:
iif(1=1, rdoYes, rdoNo).checked = True
(I'm not sure that's valid VB ... it's been more than a decade since I've had to code in it)

Question about Type Comparison ASP.NET and DBNull

I have a function that pulls articles records from an MSSQL database. Some are URLs to PDFs, and other are actual articles stored in the SQL. The articles that are stored do not have a URL (DBNull) in the record, so I want to be able to parse that. I tried a simple test:
If Row.Item("url").GetType Is GetType(DBNull) Then
//' do something here....
End If
However, I get the "Conversion from type 'DBNull' to type 'String' is not valid." exception. The funny part is, when I do a watch on the above conditional, it returns True or False.
Anyone know why this is happening and/or a way to fix this? Thanks!
I always just use this test on the record:
If IsDBNull(strSQLTiggRes("url")) Then
'Do something .
Else
'do something else
end if
Why not just use:
If Row.IsNull("url") Then
//' do something here....
End If
I like
if (DBNull.Value.Equals(Row.Item("url")))
Try
If Row.Item("url") = DBNull.Value
The error is telling you that Row.Item("url") is a System.String so the value at this point will not by DbNull.
Try something like this:
If Row.Item("url") Is Nothing Then
//' do something here....
End If
Can't you just do
If Row.Item("url") = DBNull.Value Then
End If
My preference is:
If Not Object.Equals(DBNull.Value, Row.Item("url")) Then
'Hooray!
End If
In VB, you can also use the IsDBNull function (Microsoft.VisualBasic disclaimer) directly :
If Not IsDBNull(Row.Item("url")) Then
'Hooray!
End It
Use this.
if row("ColumnName") is DBNull.value Then
'do something
end if
You will find that you must use is in this case and you nee dto compare the values not just the types. You may also want to put it into a reusable function that you can use to return nothing instead of dbnull
function checkvalue(item as object)
if item is dbnul.value then
return nothing
else
return item
end if
end function

VBScript conditional short-circuiting workaround

I have a large classic ASP app that I have to maintain, and I repeatedly find myself thwarted by the lack of short-circuit evaluation capability. E.g., VBScript won't let you get away with:
if not isNull(Rs("myField")) and Rs("myField") <> 0 then
...
...because if Rs("myField") is null, you get an error in the second condition, comparing null to 0. So I'll typically end up doing this instead:
dim myField
if isNull(Rs("myField")) then
myField = 0
else
myField = Rs("myField")
end if
if myField <> 0 then
...
Obviously, the verboseness is pretty appalling. Looking around this large code base, the best workaround I've found is to use a function the original programmer wrote, called TernaryOp, which basically grafts in ternary operator-like functionality, but I'm still stuck using a temporary variable that would not be necessary in a more full-featured language. Is there a better way? Some super-secret way that short-circuiting really does exist in VBScript?
Nested IFs (only slightly less verbose):
if not isNull(Rs("myField")) Then
if Rs("myField") <> 0 then
Maybe not the best way, but it certainly works... Also, if you are in vb6 or .net, you can have different methods that cast to proper type too.
if cint( getVal( rs("blah"), "" ) )<> 0 then
'do something
end if
function getVal( v, replacementVal )
if v is nothing then
getVal = replacementVal
else
getVal = v
end if
end function
I always used Select Case statements to short circuit logic in VB. Something like..
Select Case True
Case isNull(Rs("myField"))
myField = 0
Case (Rs("myField") <> 0)
myField = Rs("myField")
Case Else
myField = -1
End Select
My syntax may be off, been a while. If the first case pops, everything else is ignored.
If you write it as two inline IF statements, you can achieve short-circuiting:
if not isNull(Rs("myField")) then if Rs("myField") <> 0 then ...
But your then action must appear on the same line as well. If you need multiple statements after then, you can separate them with : or move your code to a subroutine that you can call. For example:
if not isNull(Rs("myField")) then if Rs("myField") <> 0 then x = 1 : y = 2
Or
if not isNull(Rs("myField")) then if Rs("myField") <> 0 then DoSomething(Rs("myField"))
Or perhaps I got the wrong end of the question. Did you mean something like iIf() in VB? This works for me:
myField = returnIf(isNothing(rs("myField")), 0, rs("myField"))
where returnIf() is a function like so:
function returnIf(uExpression, uTrue, uFalse)
if (uExpression = true) then returnIf = uTrue else returnIf = uFalse : end if
end function
Yeah it's not the best solution but what we use is something like this
function ReplaceNull(s)
if IsNull(s) or s = "" then
ReplaceNull = " "
else
ReplaceNull = s
end if
end function
Would that there were, my friend -- TernaryOp is your only hope.
Two options come to mind:
1) use len() or lenb() to discover if there is any data in the variable:
if not lenb(rs("myField"))=0 then...
2) use a function that returns a boolean:
if not isNothing(rs("myField")) then...
where isNothing() is a function like so:
function isNothing(vInput)
isNothing = false : vInput = trim(vInput)
if vartype(vInput)=0 or isEmpty(vInput) or isNull(vInput) or lenb(vInput)=0 then isNothing = true : end if
end function
You may be able to just use Else to catch nulls, ""s, etc.
If UCase(Rs("myField")) = "THING" then
'Do Things
elseif UCase(Rs("myField")) = "STUFF" then
'Do Other Stuff
else
'Invalid data, such as a NULL, "", etc.
'Throw an error, do nothing, or default action
End If
I've tested this in my code and it's currently working. Might not be right for everyone's situation though.

Resources