What is the best way to deal with DBNull's

后端 未结 14 945
迷失自我
迷失自我 2020-12-02 15:45

I frequently have problems dealing with DataRows returned from SqlDataAdapters. When I try to fill in an object using code like this:



        
相关标签:
14条回答
  • 2020-12-02 16:03

    You should also look at the extension methods. Here are some examples to deal with this scenerio.

    Recommended read

    0 讨论(0)
  • 2020-12-02 16:06

    Brad Abrams posted something related just a couple of days ago http://blogs.msdn.com/brada/archive/2009/02/09/framework-design-guidelines-system-dbnull.aspx

    In Summary "AVOID using System.DBNull. Prefer Nullable instead."

    And here is my two cents (of untested code :) )

    // Or if (row["fooColumn"] == DBNull.Value)
    if (row.IsNull["fooColumn"])
    {
       // use a null for strings and a Nullable for value types 
       // if it is a value type and null is invalid throw a 
       // InvalidOperationException here with some descriptive text. 
       // or dont check for null at all and let the cast exception below bubble  
       value = null;
    }
    else
    {
       // do a direct cast here. dont use "as", "convert", "parse" or "tostring"
       // as all of these will swallow the case where is the incorect type.
       // (Unless it is a string in the DB and really do want to convert it)
       value = (string)row["fooColumn"];
    }
    

    And one question... Any reason you are not using an ORM?

    0 讨论(0)
  • 2020-12-02 16:09

    If you aren't using nullable types, the best thing to do is check to see if the column's value is DBNull. If it is DBNull, then set your reference to what you use for null/empty for the corresponding datatype.

    DataRow row = ds.Tables[0].Rows[0];
    string value;
    
    if (row["fooColumn"] == DBNull.Value)
    {
       value = string.Empty;
    }
    else 
    {
       value = Convert.ToString(row["fooColumn"]);
    }
    

    As Manu said, you can create a convert class with an overloaded convert method per type so you don't have to pepper your code with if/else blocks.

    I will however stress that nullable types is the better route to go if you can use them. The reasoning is that with non-nullable types, you are going to have to resort to "magic numbers" to represent null. For example, if you are mapping a column to an int variable, how are you going to represent DBNull? Often you can't use 0 because 0 has a valid meaning in most programs. Often I see people map DBNull to int.MinValue, but that could potentially be problematic too. My best advice is this:

    • For columns that can be null in the database, use nullable types.
    • For columns that cannot be null in the database, use regular types.

    Nullable types were made to solve this problem. That being said, if you are on an older version of the framework or work for someone who doesn't grok nullable types, the code example will do the trick.

    0 讨论(0)
  • 2020-12-02 16:13

    It is worth mentioning, that DBNull.Value.ToString() equals String.Empty

    You can use this to your advantage:

    DataRow row = ds.Tables[0].Rows[0];
    string value = row["name"].ToString();
    

    However, that only works for Strings, for everything else I would use the linq way or a extension method. For myself, I have written a little extension method that checks for DBNull and even does the casting via Convert.ChangeType(...)

    int value = row.GetValueOrDefault<int>("count");
    int value = row.GetValueOrDefault<int>("count", 15);
    
    0 讨论(0)
  • 2020-12-02 16:14

    For some reason I've had problems with doing a check against DBNull.Value, so I've done things slightly different and leveraged a property within the DataRow object:

    if (row.IsNull["fooColumn"])
    {
       value = string.Empty();
    }
    {
    else
    {
       value = row["fooColumn"].ToString;
    }
    
    0 讨论(0)
  • 2020-12-02 16:17

    You can also test with Convert.IsDBNull (MSDN).

    0 讨论(0)
提交回复
热议问题