Results 1 to 12 of 12

Thread: [RESOLVED] How to use Nullable types?

  1. #1

    Thread Starter
    Frenzied Member
    Join Date
    Jan 2010
    Location
    Connecticut
    Posts
    1,687

    Resolved [RESOLVED] How to use Nullable types?

    I'm converting an Access VBA app to VB.NET. It has dates defined as variants or objects to handle null values. I thought this would be a great chance to use the Nullable type. But I can't get it to work. Either it is inappropriate for what I am trying to use it for, or I am doing it wrong. Anyone know how to use it? Reader is a SqlDataReader.

    Code:
    mdtDeniedDate = DirectCast(Reader("DeniedDate"), DateTime?)
    OR

    Code:
    mdtDeniedDate = CType(Reader("DeniedDate"), DateTime?)
    The field returns
    {System.DBNull}
    System.DBNull: {System.DBNull}
    And I just get the error "Specified cast is not valid."

    Declaration:
    Code:
    Private mdtDeniedDate As DateTime?
    Even the statement
    Code:
    mdtDeniedDate = Reader("DeniedDate")
    Returns an error 'System.DBNull' cannot be converted to 'Date'.

    I was hoping I didn't have to put a lot of If .. Null statements throughtout the code, but that is my only option unless someone has any other idea.
    VB6 Library

    If I helped you then please help me and rate my post!
    If you solved your problem, then please mark the post resolved

  2. #2
    Fanatic Member stlaural's Avatar
    Join Date
    Sep 2007
    Location
    Quebec, Canada
    Posts
    683

    Re: How to use Nullable types?

    Hey MarMan,

    DBNull is not exactly the same as Null. Null really means that a reference-type variable has no reference while the DBNull value can also mean that a variable or a table field was never initialized, it represent the abscence of a known value. Its not a big difference but that's why you are getting the error you get. Have a look here for more info.

    the simple solution is to use an "if" statement to check for DBNull value.
    Last edited by stlaural; Aug 25th, 2010 at 02:03 PM.
    Alex
    .NET developer
    "No. Not even in the face of Armageddon. Never compromise." (Walter Kovacs/Rorschach)

    Things to consider before posting.
    Don't forget to rate the posts if they helped and mark thread as resolved when they are.


    .Net Regex Syntax (Scripting) | .Net Regex Language Element | .Net Regex Class | DateTime format | Framework 4.0: what's new
    My fresh new blog : writingthecode, even if I don't post much.

    System: Intel i7 920, Kingston SSDNow V100 64gig, HDD WD Caviar Black 1TB, External WD "My Book" 500GB, XFX Radeon 4890 XT 1GB, 12 GBs Tri-Channel RAM, 1x27" and 1x23" LCDs, Windows 10 x64, ]VS2015, Framework 3.5 and 4.0

  3. #3
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: How to use Nullable types?

    *argh, beaten!*

    DBNull isn't the same as Nothing. They express the same concept, but since they aren't the same thing you can't treat them as such. The documentation for DBNull tries to help, but it's still kind of weird:
    Do not confuse the notion of nullNothingnullptra null reference (Nothing in Visual Basic) in an object-oriented programming language with a DBNull object. In an object-oriented programming language, nullNothingnullptra null reference (Nothing in Visual Basic) means the absence of a reference to an object. DBNull represents an uninitialized variant or nonexistent database column.
    That doesn't mean you can't use nullable types, but it does mean it's not as straightforward. For example, this is what your code should end up looking like:
    Code:
    Dim rawValue As Object = Reader("DeniedDate")
    Dim deniedDate As DateTime?
    
    If rawValue Is DBNull.Value Then
        deniedDate = Nothing
    Else
        deniedDate = CType(rawValue, DateTime?)
    End If
    The answer to this StackOverflow question seems to indicate that LINQ to DataSets could work in this scenario. It's not something I've tried extensively but it would definitely put some sugar around it. (There'd still be the if logic behind the scenes but it's hidden.)

  4. #4

    Thread Starter
    Frenzied Member
    Join Date
    Jan 2010
    Location
    Connecticut
    Posts
    1,687

    Re: How to use Nullable types?

    Thanks guys. I didn't want to use Nothiing because then I don't know if deniedDate was never set, or there is no date in the DB. So it sounds like Nullable is useless. If the following code is valid (it is):

    Code:
    Dim dtmDeniedDate1 as DateTime
    Dim dtmDeniedDate2 as DateTime?
    
    dtmDeniedDate1 = Nothing
    dtmDeniedDate2 = Nothing
    And the following is invalid:
    Code:
    Dim dtmDeniedDate1 as DateTime
    Dim dtmDeniedDate2 as DateTime?
    
    dtmDeniedDate1 = vbNull
    dtmDeniedDate2 = vbNull
    What use is Nullable then?
    VB6 Library

    If I helped you then please help me and rate my post!
    If you solved your problem, then please mark the post resolved

  5. #5
    Fanatic Member stlaural's Avatar
    Join Date
    Sep 2007
    Location
    Quebec, Canada
    Posts
    683

    Re: How to use Nullable types?

    I haven't used Nullables much, some times on variable and sometime on certain method parameters so I'm not the best person to say how usefull they are. Basically you use a nullable when you need your object to have a value that says "undefined". But as you just discovered they don't solve all your problems if you are using them in a Database oriented application.
    Alex
    .NET developer
    "No. Not even in the face of Armageddon. Never compromise." (Walter Kovacs/Rorschach)

    Things to consider before posting.
    Don't forget to rate the posts if they helped and mark thread as resolved when they are.


    .Net Regex Syntax (Scripting) | .Net Regex Language Element | .Net Regex Class | DateTime format | Framework 4.0: what's new
    My fresh new blog : writingthecode, even if I don't post much.

    System: Intel i7 920, Kingston SSDNow V100 64gig, HDD WD Caviar Black 1TB, External WD "My Book" 500GB, XFX Radeon 4890 XT 1GB, 12 GBs Tri-Channel RAM, 1x27" and 1x23" LCDs, Windows 10 x64, ]VS2015, Framework 3.5 and 4.0

  6. #6

    Thread Starter
    Frenzied Member
    Join Date
    Jan 2010
    Location
    Connecticut
    Posts
    1,687

    Re: How to use Nullable types?

    Do you know how to set them to be "undefined" as opposed to "uninitialized" (Nothing)?
    VB6 Library

    If I helped you then please help me and rate my post!
    If you solved your problem, then please mark the post resolved

  7. #7
    Fanatic Member stlaural's Avatar
    Join Date
    Sep 2007
    Location
    Quebec, Canada
    Posts
    683

    Re: How to use Nullable types?

    By "undefined" I mean the meaning of the value in a certain context. Let's say you are doing a questionnaire application with true/false questions and you wish to store all answers in a boolean variable. You could use Nullables in order to represent unanswered questions. As I said I didn't use it much yet but this is one example where they can be usefull.
    Alex
    .NET developer
    "No. Not even in the face of Armageddon. Never compromise." (Walter Kovacs/Rorschach)

    Things to consider before posting.
    Don't forget to rate the posts if they helped and mark thread as resolved when they are.


    .Net Regex Syntax (Scripting) | .Net Regex Language Element | .Net Regex Class | DateTime format | Framework 4.0: what's new
    My fresh new blog : writingthecode, even if I don't post much.

    System: Intel i7 920, Kingston SSDNow V100 64gig, HDD WD Caviar Black 1TB, External WD "My Book" 500GB, XFX Radeon 4890 XT 1GB, 12 GBs Tri-Channel RAM, 1x27" and 1x23" LCDs, Windows 10 x64, ]VS2015, Framework 3.5 and 4.0

  8. #8
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: How to use Nullable types?

    Nullables are what the database would likely return had they existed when ADO .NET was designed. They came much later.

    I can't really defend or attack DBNull due to my lack of experience with database code, but I imagine the justification is the designers wanted a very clear separation between "this variable references no object" and "the value of this database column is null". Here's some speculation.

    It's easy to imagine a code construct like this:
    Code:
    Dim result As Object = Nothing
    Try
        ' do some stuff
        result = reader("Name")
    Catch ex As Exception
        ' Do something about the error, then continue
        result = Nothing
    End Try
    
    If result Is Nothing Then
    ...
    If it were valid for "the database value is null" to return Nothing, we'd be in a pickle here. Is result Nothing because an exception was thrown, or is it Nothing because the internal value is null? To know for sure, we'd have to add some kind of extra flag:
    Code:
    Dim result As Object = Nothing
    Dim exceptionWasThrown As Boolean = False
    Try
        ...
    Catch ...
        exceptionWasThrown = True
        ...
    End Try
    
    If exceptionWasThrown Then
        
    ElseIf result = Nothing Then
    ...
    It's not that big of a deal until you want to return result from a function call; since you can't return two values, you'd have to rely on a ByRef parameter and those are generally discouraged in API design.

    Now let's approach the situation when DBNull is present:
    Code:
    Dim result As Object = Nothing
    Try
        ' do some stuff
        result = reader("Name")
    Catch ex As Exception
        ' Do something about the error, then continue
        result = Nothing
    End Try
    
    If IsDBNull(result) Then
        ...
    ElseIf result Is Nothing then
        ...
    Now we don't need the extra information to tell us if an exception was thrown or if the column just had no value. DBNull serves us for the "no value" case. A nullable value wouldn't really serve this purpose; you'd need the flag in order to decide whether a value of Nothing meant "no value" or "something got borked".

    Nullables are better when you want to express a "value or failure" scenario. In the scenarios above, I've described a three-state "value, no value, or failure" scenario since Nothing has to be treated like a special value. Nullables don't handle the three-state scenario since they can only communicate "value or no value" with no extra information.

    Why wasn't ADO .NET updated to use nullables? Beats me. I could speculate that it's because nullables are still kind of a pain to work with, but seeing that LINQ example makes me feel like MS felt the LINQ support for nullables was adequate.

  9. #9
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: How to use Nullable types?

    Nullable value types are just like reference types in that they either contain a value or they don't. There's no way to differentiate between a value not having been assigned and a null value having specifically been assigned with nullable value type any more than there is with reference types. If you're reading data from a database and you want to turn DBNull.Value into nothing then, assuming VB 2008 or later, you can do this:
    vb.net Code:
    1. Dim myDate As Date? = If(myDataReader.IsDBNull(index), DirectCast(Nothing, Date?), myDataReader.GetDateTime(index))
    As you can see, the data reader provides a specific method for determining if a field is NULL, as does the DataRow class.
    Last edited by jmcilhinney; Aug 27th, 2010 at 09:17 PM. Reason: Added required cast, without which a null value resulted in a default Date instead of Nothing
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  10. #10
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: How to use Nullable types?

    Note that, if you need to go the other way, you can do something like this:
    vb.net Code:
    1. myDataRow("DateColumn") = If(myDate.HasValue, CObj(myDate.Value), DBNull.Value)
    The If operator is much more succinct than an If statement in such situations.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  11. #11
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: How to use Nullable types?

    I've changed the code in post #9 to use the GetDateTime method and therefore remove the need for a cast. Given that each data reader class has methods like GetDateTime, wouldn't it be nice if it had similar methods for nullable types, e.g. GetNullableDateTime? It doesn't, but you can easily create your own extension methods, e.g.
    vb.net Code:
    1. Imports System.Data.Common
    2. Imports System.Runtime.CompilerServices
    3.  
    4. Public Module DataReaderExtensions
    5.  
    6.     <Extension()> _
    7.     Public Function GetNullableDateTime(ByVal sender As DbDataReader, ByVal i As Integer) As DateTime?
    8.         Return If(sender.IsDBNull(i), Nothing, sender.GetDateTime(i))
    9.     End Function
    10.  
    11. End Module
    Now you can use that just like the GetDateTime method, e.g.
    vb.net Code:
    1. Dim myDate As Date? = myDataReader.GetNullableDateTime(columnIndex)
    You might also create an extension method for all nullable value types:
    vb.net Code:
    1. Public Module NullableExtensions
    2.  
    3.     <Extension()> _
    4.     Public Function GetDataValue(Of T As Structure)(ByVal sender As T?) As Object
    5.         Return If(sender.HasValue, CObj(sender.Value), DBNull.Value)
    6.     End Function
    7.  
    8. End Module
    so the code in post #10 would then become:
    vb.net Code:
    1. myDataRow("DateColumn") = myDate.GetDataValue()
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  12. #12

    Thread Starter
    Frenzied Member
    Join Date
    Jan 2010
    Location
    Connecticut
    Posts
    1,687

    Re: How to use Nullable types?

    Thanks everyone. I'm a little disappointed with the nullable type. My imagination gave it more strength than it supplies.
    VB6 Library

    If I helped you then please help me and rate my post!
    If you solved your problem, then please mark the post resolved

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width