handling dbnull data in vb.net
Asked Answered
D

14

81

I want to generate some formatted output of data retrieved from an MS-Access database and stored in a DataTable object/variable, myDataTable. However, some of the fields in myDataTable cotain dbNull data. So, the following VB.net code snippet will give errors if the value of any of the fields lastname, intials, or sID is dbNull.

   dim myDataTable as DataTable
   dim tmpStr as String
   dim sID as Integer = 1

   ...
   myDataTable = myTableAdapter.GetData() ' Reads the data from MS-Access table
   ...

   For Each myItem As DataRow In myDataTable.Rows

    tmpStr = nameItem("lastname") + " " + nameItem("initials")

    If myItem("sID")=sID Then
        ' Do something
    End If

    ' print tmpStr

   Next

So, how do i get the above code to work when the fields may contain dbNull without having to check each time if the data is dbNull as in this question?

David answered 21/10, 2008 at 18:3 Comment(2)
can you indicate WHERE (on which line) error occurs ? I suppose on If MyItem("sID")=sID but I'm not sure.Utopian
Are you sure that field name is "sID" ? It is special that a column name begin with "s"; normally prefixing a variable by "s" is to indicate that it is a String variable.Utopian
S
145

The only way that i know of is to test for it, you can do a combined if though to make it easy.

If NOT IsDbNull(myItem("sID")) AndAlso myItem("sID") = sId Then
   'Do success
ELSE
   'Failure
End If

I wrote in VB as that is what it looks like you need, even though you mixed languages.

Edit

Cleaned up to use IsDbNull to make it more readable

Sinter answered 21/10, 2008 at 18:7 Comment(5)
Thanks for your answer. I guess it looks like mixed languanges because of the way I coded the comments with "//" instead of ticks for VB.net comments?David
Yup! And the == in the comparisonSinter
I think I fixed the code in the question to be pure VB.Net code. Thanks for your answers.David
10 years later. "+" as well. :PFiredog
The DataRow class has its own IsNull method. That code would also not compile with Option Strict On.Schumacher
S
37

I got tired of dealing with this problem so I wrote a NotNull() function to help me out.

Public Shared Function NotNull(Of T)(ByVal Value As T, ByVal DefaultValue As T) As T
        If Value Is Nothing OrElse IsDBNull(Value) Then
                Return DefaultValue
        Else
                Return Value
        End If
End Function

Usage:

If NotNull(myItem("sID"), "") = sID Then
  ' Do something
End If

My NotNull() function has gone through a couple of overhauls over the years. Prior to Generics, I simply specified everything as an Object. But I much prefer the Generic version.

Scutellation answered 12/11, 2009 at 17:10 Comment(5)
+1 Works very well, I've named it IsNull() as per SQL Server.Wag
I prefer making the 2nd variable optional so that the signature is like this: Public Shared Function NotNull(Of T)(ByVal Value As T, Optional ByVal DefaultValue As T = Nothing) As T and it can be called as If NotNull(myItem("sID")) = sID Then or as listed above.Calpe
Doesn't work for me using VS 2008: tried to use this method with dataset generated dataTable and didn't work. NotNull(rw.computer) fails because the Dataset.Designer.vb code tries to convert to string before passing as argument. I suppose it would work with generic DataTable.Taxis
Put this into it when using nullable of integer: Public Function NotNull(ByVal value As Integer?) As Integer Return NotNull(value, 0) End FunctionHerbert
I love this method. Concise and effective. +1Tilla
S
12

You can also use the Convert.ToString() and Convert.ToInteger() methods to convert items with DB null effectivly.

Sinter answered 21/10, 2008 at 18:9 Comment(0)
R
6

A variation on Steve Wortham's code, to be used nominally with nullable types:

Private Shared Function GetNullable(Of T)(dataobj As Object) As T
    If Convert.IsDBNull(dataobj) Then
        Return Nothing
    Else
        Return CType(dataobj, T)
    End If
End Function

e.g.

mynullable = GetNullable(Of Integer?)(myobj)

You can then query mynullable (e.g., mynullable.HasValue)

Resort answered 31/3, 2012 at 5:52 Comment(0)
W
3

Microsoft came up with DBNull in .NET 1.0 to represent database NULL. However, it's a pain in the behind to use because you can't create a strongly-typed variable to store a genuine value or null. Microsoft sort of solved that problem in .NET 2.0 with nullable types. However, you are still stuck with large chunks of API that use DBNull, and they can't be changed.

Just a suggestion, but what I normally do is this:

  1. All variables containing data read from or written to a database should be able to handle null values. For value types, this means making them Nullable(Of T). For reference types (String and Byte()), this means allowing the value to be Nothing.
  2. Write a set of functions to convert back and forth between "object that may contain DBNull" and "nullable .NET variable". Wrap all calls to DBNull-style APIs in these functions, then pretend that DBNull doesn't exist.
Windermere answered 7/6, 2009 at 13:30 Comment(0)
H
2

You can use the IsDbNull function:

  If  IsDbNull(myItem("sID")) = False AndAlso myItem("sID")==sID Then
    // Do something
End If
Heated answered 21/10, 2008 at 18:8 Comment(0)
A
2

If you are using a BLL/DAL setup try the iif when reading into the object in the DAL

While reader.Read()
 colDropdownListNames.Add(New DDLItem( _
 CType(reader("rid"), Integer), _
 CType(reader("Item_Status"), String), _
 CType(reader("Text_Show"), String), _
 CType( IIf(IsDBNull(reader("Text_Use")), "", reader("Text_Use")) , String), _
 CType(reader("Text_SystemOnly"), String), _
 CType(reader("Parent_rid"), Integer)))
End While
Aceous answered 5/9, 2012 at 12:25 Comment(0)
D
1

For the rows containing strings, I can convert them to strings as in changing

tmpStr = nameItem("lastname") + " " + nameItem("initials")

to

tmpStr = myItem("lastname").toString + " " + myItem("intials").toString

For the comparison in the if statement myItem("sID")=sID, it needs to be change to

myItem("sID").Equals(sID)

Then the code will run without any runtime errors due to vbNull data.

David answered 21/10, 2008 at 18:8 Comment(0)
M
1
   VB.Net
   ========
    Dim da As New SqlDataAdapter
    Dim dt As New DataTable
    Call conecDB()        'Connection to Database
    da.SelectCommand = New SqlCommand("select max(RefNo) from BaseData", connDB)

    da.Fill(dt)

    If dt.Rows.Count > 0 And Convert.ToString(dt.Rows(0).Item(0)) = "" Then
        MsgBox("datbase is null")

    ElseIf dt.Rows.Count > 0 And Convert.ToString(dt.Rows(0).Item(0)) <> "" Then
        MsgBox("datbase have value")

    End If
Mixologist answered 27/11, 2013 at 15:40 Comment(0)
B
1

I think this should be much easier to use:

select ISNULL(sum(field),0) from tablename

Copied from: http://www.codeproject.com/Questions/736515/How-do-I-avoide-Conversion-from-type-DBNull-to-typ

Bathometer answered 26/9, 2016 at 20:33 Comment(0)
S
0

Hello Friends

This is the shortest method to check db Null in DataGrid and convert to string

  1. create the cell validating event and write this code
  2. If Convert.ToString(dgv.CurrentCell.Value) = "" Then
  3. CurrentCell.Value = ""
  4. End If
Strachan answered 11/8, 2013 at 10:10 Comment(0)
T
0

This is BY FAR the easiest way to convert DBNull to a string. The trick is that you CANNOT use the TRIM function (which was my initial problem) when referring to the fields from the database:

BEFORE (produced error msg):

Me.txtProvNum.Text = IIf(Convert.IsDBNull(TRIM(myReader("Prov_Num"))), "", TRIM(myReader("Prov_Num")))

AFTER (no more error msg :-) ):

Me.txtProvNum.Text = IIf(Convert.IsDBNull(myReader("Prov_Num")), "", myReader("Prov_Num"))
Ternary answered 7/2, 2014 at 17:7 Comment(0)
P
0

Simple, but not obvious.

DbNull.Value.Equals(myValue)

I hate VB.NET

Peoria answered 10/11, 2021 at 17:12 Comment(0)
U
0

For your problem, you can use following special workaround coding that only exists in VB.Net.

Dim nId As Integer = dr("id") + "0"

This code will replace DBNull value contained in id column by integer 0.

The only acceptable default value is "0" because this expression must also be used when dr("id") is not NULL !

So, using this technic, your code would be

   Dim myDataTable as DataTable
   Dim s as String
   Dim sID as Integer = 1

   ...
   myDataTable = myTableAdapter.GetData() ' Reads the data from MS-Access table
   ...

   For Each myItem As DataRow In myDataTable.Rows
       s = nameItem("lastname") + " " + nameItem("initials")
       If myItem("sID") + "0" = sID Then
           ' Do something
       End If
   Next

I have tested this solution and it works on my PC on Visual Studio 2022.

PS: if sID can be equal to 0 and you want to do something distinct when dr("sID") value is NULL, you must also adept you program and perhaps use Extension as proposed at end of this answer.

I have tested following statements

Dim iNo1 As Integer = dr("numero") + "0"
Dim iNo2 As Integer = dr("numero") & "0" '-> iNo = 10 when dr() = 1
Dim iNo3 As Integer = dr("numero") + "4" '-> iNo = 5  when dr() = 1
Dim iNo4 As Integer = dr("numero") & "4" '-> iNo = 14 when dr() = 1
Dim iNo5 As Integer = dr("numero") + "" -> System.InvalidCastException : 'La conversion de la chaîne "" en type 'Integer' n'est pas valide.'
Dim iNo6 As Integer = dr("numero") & "" -> System.InvalidCastException : 'La conversion de la chaîne "" en type 'Integer' n'est pas valide.'
Dim iNo7 As Integer = "" + dr("numero") -> System.InvalidCastException : 'La conversion de la chaîne "" en type 'Integer' n'est pas valide.'
Dim iNo8 As Integer = "" & dr("numero") -> System.InvalidCastException : 'La conversion de la chaîne "" en type 'Integer' n'est pas valide.'
Dim iNo9 As Integer = "0" + dr("numero")
Dim iNo0 As Integer = "0" & dr("numero")

Following statements works also correctly

Dim iNo9 As Integer = "0" + dr("numero")
Dim iNo0 As Integer = "0" & dr("numero")

I recognize that is a little tricky.

If trick are not your tips, you can also define an Extension so that following code works.

Dim iNo = dr.GetInteger("numero",0)

where GetInteger() code can be following

Module Extension
    '***********************************************************************
    '* GetString()
    '***********************************************************************

    <Extension()>
    Public Function GetString(ByRef rd As SqlDataReader, ByRef sName As String, Optional ByVal sDefault As String = "") As String
        Return GetString(rd, rd.GetOrdinal(sName), sDefault)
    End Function

    <Extension()>
    Public Function GetString(ByRef rd As SqlDataReader, ByVal iCol As Integer, Optional ByVal sDefault As String = "") As String
        If rd.IsDBNull(iCol) Then
            Return sDefault
        Else
            Return rd.Item(iCol).ToString()
        End If
    End Function

    '***********************************************************************
    '* GetInteger()
    '***********************************************************************

    <Extension()>
    Public Function GetInteger(ByRef rd As SqlDataReader, ByRef sName As String, Optional ByVal iDefault As Integer = -1) As Integer
        Return GetInteger(rd, rd.GetOrdinal(sName), iDefault)
    End Function

    <Extension()>
    Public Function GetInteger(ByRef rd As SqlDataReader, ByVal iCol As Integer, Optional ByVal iDefault As Integer = -1) As Integer
        If rd.IsDBNull(iCol) Then
            Return iDefault
        Else
            Return rd.Item(iCol)
        End If
    End Function

End Module

These methods are more explicitely and less tricky.

In addition, it is possible to define default values other than ZERO and also specific version as GetBoolean() or GetDate(), etc ...

Another possibility is to report SQL default conversion in SQL command using COALESCE SQL command !

Utopian answered 22/11, 2022 at 10:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.