Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. OdbcDataReader calling IsDBNull changes the behaviour of Get methods

OdbcDataReader calling IsDBNull changes the behaviour of Get methods

Scheduled Pinned Locked Moved C#
question
25 Posts 6 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Dan Mos

    OK. Heres what I would do. Run that query in SQLManagementStudio and check the results. Are there any? Or some with a field null or...

    All the best, Dan

    _ Offline
    _ Offline
    __John_
    wrote on last edited by
    #14

    Hi MDL=Moshu, thanks for looking at this. The code now looks like this...

    int nColName = odbcDataReader.GetOrdinal(@"name");
    int nColNumber = odbcDataReader.GetOrdinal(@"iq");

    while (odbcDataReader.Read())
    {
        if(odbcDataReader.IsDBNull(nColNumber))
        {
            continue;
        }
    
        int nNumber = odbcDataReader.GetInt32(nColNumber);
    
        string strNumber = odbcDataReader.GetString(nColNumber);
    
    }
    

    No nulls are returned and the behaviour is the same ie. with the call to IsDBNull() GetString() fails, and without it, GetInt32() fails.

    D 1 Reply Last reply
    0
    • D Dan Mos

      Also since you are not using a Select * statement, I would drop the lines of code that get the ordinals. You know them name is 0 and iq is 1 so in a nutshell:

       while(dr.Read()){
       string name = dr\[0\].ToString();
       int iq = (int)dr\[1\];
      

      }

      All the best, Dan

      _ Offline
      _ Offline
      __John_
      wrote on last edited by
      #15

      Thanks dan, But I think my way is more robust and future proof. ie. it will still work even with 'SELECT *'. - John

      D L 2 Replies Last reply
      0
      • _ __John_

        Hi MDL=Moshu, thanks for looking at this. The code now looks like this...

        int nColName = odbcDataReader.GetOrdinal(@"name");
        int nColNumber = odbcDataReader.GetOrdinal(@"iq");

        while (odbcDataReader.Read())
        {
            if(odbcDataReader.IsDBNull(nColNumber))
            {
                continue;
            }
        
            int nNumber = odbcDataReader.GetInt32(nColNumber);
        
            string strNumber = odbcDataReader.GetString(nColNumber);
        
        }
        

        No nulls are returned and the behaviour is the same ie. with the call to IsDBNull() GetString() fails, and without it, GetInt32() fails.

        D Offline
        D Offline
        Dan Mos
        wrote on last edited by
        #16

        This is my final reply. First check my post below. Second you're using nColNumber for both the name and the iq. That's not right and I pointed it out on my first post to this thread. If for some reason you want a string representation of the number/iq then just use strNumber = nNumber.ToString(); Hope it helps. I'm out of CP for today. Going to program some beers now. :)

        All the best, Dan

        1 Reply Last reply
        0
        • _ __John_

          Thanks dan, But I think my way is more robust and future proof. ie. it will still work even with 'SELECT *'. - John

          D Offline
          D Offline
          Dan Mos
          wrote on last edited by
          #17

          True. Then use dr["name"] and dr["iq"] and it will be future proof.

          All the best, Dan

          _ 1 Reply Last reply
          0
          • D Dan Mos

            In your statement var Val is the same as int Val cause GetInt32() returns a int on success. var Val = odbcDataReader[nColNumber]; is what you should use. Val will be an object of type Object and you can check for null and do the casting later. This is obviously for debugging purposes. Cause the cast and checking are not necessarily once you figure out the problem.

            All the best, Dan

            _ Offline
            _ Offline
            __John_
            wrote on last edited by
            #18

            Hi Dan, Using the indexer, casting to an int always works and casting to a string always fails (invalid cast). So the behavour is predictable and my problem 'kind of' goes away. So for now I will use the indexer and not use the Get???? methods. @PIEBALDconsult: You mentioned indexers earlier but I was not sure what you were getting at. Turns out you were on to something. Thanks.

            D 1 Reply Last reply
            0
            • D Dan Mos

              True. Then use dr["name"] and dr["iq"] and it will be future proof.

              All the best, Dan

              _ Offline
              _ Offline
              __John_
              wrote on last edited by
              #19

              Hi MDL=>Moshu, Using an indexer as you sagest (with column name) is fine if you only have a small number of fields, but if the number of fields is higher then I think you will take a performance hit.

              1 Reply Last reply
              0
              • _ __John_

                Thanks dan, But I think my way is more robust and future proof. ie. it will still work even with 'SELECT *'. - John

                L Offline
                L Offline
                Luc Pattyn
                wrote on last edited by
                #20

                __John_ wrote:

                my way is more robust

                That doesn't sound very convincing as your code does not produce the expected results to begin with. Have you already figured nColNumber is appearing too many times in your code? (courtesy MDL) :omg:

                Luc Pattyn [My Articles] Nil Volentibus Arduum

                1 Reply Last reply
                0
                • _ __John_

                  Hi Dan, Using the indexer, casting to an int always works and casting to a string always fails (invalid cast). So the behavour is predictable and my problem 'kind of' goes away. So for now I will use the indexer and not use the Get???? methods. @PIEBALDconsult: You mentioned indexers earlier but I was not sure what you were getting at. Turns out you were on to something. Thanks.

                  D Offline
                  D Offline
                  Dan Mos
                  wrote on last edited by
                  #21

                  Again you used nColNumber twice. You should have used nColNumber and nColName. That was your problem. And yeah I don't use GetXXX either. But that wasn't what caused the exception. You tried to get a string from an int DB value or a int form a varchar DB value courtesy of using twice nColNumber.

                  All the best, Dan

                  1 Reply Last reply
                  0
                  • _ __John_

                    Hi, If I do...

                    int nColName   = odbcDataReader.GetOrdinal(@"name");
                    int nColNumber = odbcDataReader.GetOrdinal(@"iq");
                    
                    while (odbcDataReader.Read())
                    {
                        string strName = odbcDataReader.GetString(nColNumber);
                        int nNumber = odbcDataReader.GetInt32(nColNumber);
                    }
                    

                    GetString() succeeds. GetInt32() throws an exception... [System.InvalidCastException] = {"Specified cast is not valid."} However if I do...

                    int nColName   = odbcDataReader.GetOrdinal(@"name");
                    int nColNumber = odbcDataReader.GetOrdinal(@"iq");
                    
                    while (odbcDataReader.Read())
                    {
                        odbcDataReader.IsDBNull(nColNumber);
                    
                        int nNumber = odbcDataReader.GetInt32(nColNumber);
                    
                        string strNumber = odbcDataReader.GetString(nColNumber);
                    
                    }
                    

                    Now GetInt32() succeeds. And GetString() throws an exception... [System.InvalidCastException] = {"Unable to cast object of type 'System.Int32' to type 'System.String'."} FYI: The column in question 'IQ' is of type 'int'. It seems that calling IsDBNull() first, changes the behaviour of the Get methods. Can anyone explain what is going on? Thanks - John.

                    E Offline
                    E Offline
                    Ennis Ray Lynch Jr
                    wrote on last edited by
                    #22

                    Your code changed. When you test things you should change 1 item at a time, however, you have also changed order and type. In your last example, you are calling GetString and GetInt32 on nColNumber which refers to an integer, your code should read:

                    int nameColumn = odbcDataReader.GetOrdinal(@"name");
                    int idColumn = odbcDataReader.GetOrdinal(@"iq");
                    while (odbcDataReader.Read()){
                    odbcDataReader.IsDBNull(idColumn);
                    int iqValue= odbcDataReader.GetInt32(idColumn);
                    string nameValue = odbcDataReader.GetString(nameColumn );
                    }

                    I just typed it in the post window but you can see how different variable names make it easier to see.

                    Need custom software developed? I do custom programming based primarily on MS tools with an emphasis on C# development and consulting. I also do Android Programming as I find it a refreshing break from the MS. "And they, since they Were not the one dead, turned to their affairs" -- Robert Frost

                    1 Reply Last reply
                    0
                    • D Dan Mos

                      Also since you are not using a Select * statement, I would drop the lines of code that get the ordinals. You know them name is 0 and iq is 1 so in a nutshell:

                       while(dr.Read()){
                       string name = dr\[0\].ToString();
                       int iq = (int)dr\[1\];
                      

                      }

                      All the best, Dan

                      P Offline
                      P Offline
                      PIEBALDconsult
                      wrote on last edited by
                      #23

                      MDL=>Moshu wrote:

                      string name = dr[0].ToString();

                      It's already a string, just cast it -- string name = (string) dr[0]; , no need to call a method.

                      D 1 Reply Last reply
                      0
                      • P PIEBALDconsult

                        MDL=>Moshu wrote:

                        string name = dr[0].ToString();

                        It's already a string, just cast it -- string name = (string) dr[0]; , no need to call a method.

                        D Offline
                        D Offline
                        Dan Mos
                        wrote on last edited by
                        #24

                        True. Is there a performance reason too, or just style? Cause if there is one, I might need to change some lines of code. I've always happily used ToString() on datareader where the element is a text/string. :)

                        All the best, Dan

                        P 1 Reply Last reply
                        0
                        • D Dan Mos

                          True. Is there a performance reason too, or just style? Cause if there is one, I might need to change some lines of code. I've always happily used ToString() on datareader where the element is a text/string. :)

                          All the best, Dan

                          P Offline
                          P Offline
                          PIEBALDconsult
                          wrote on last edited by
                          #25

                          There must be at least a small overhead in calling the method.

                          1 Reply Last reply
                          0
                          Reply
                          • Reply as topic
                          Log in to reply
                          • Oldest to Newest
                          • Newest to Oldest
                          • Most Votes


                          • Login

                          • Don't have an account? Register

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • World
                          • Users
                          • Groups