12

How can I add values that a SqlDataReader returns to a generic List? I have a method where I use SqlDataReader to get CategoryID from a Category table. I would like to add all the CategoryID a generic List.

This dose not work because it returns only one categoryID and that is the last one. I want to add all the categoryID to the list and then return them.

How do I do that?

SqlConnection connection = null;
SqlDataReader reader = null;
SqlCommand cmd = null;

try
{
    connection = new SqlConnection(connectionString);
    cmd = new SqlCommand("select CategoryID from Categories", connection );

    connection.Open();

    List<int> catID = new List<int>();
    dr = cmd.ExecuteReader();
    while (dr.Read())
    {
        catID.Add(Convert.ToInt32(dr["CategoryID"].ToString()));
    }
}
finally
{
    if (connection  != null)
        connection.Close();
}
return catID;
parsley72
  • 8,449
  • 8
  • 65
  • 98
Erik
  • 225
  • 2
  • 5
  • 7

5 Answers5

15

Try like this, it's better, safer, uses lazy loading, less code, working, ...:

public IEnumerable<int> GetIds()
{
    using (var connection = new SqlConnection(connectionString))
    using (var cmd = connection.CreateCommand())
    {
        connection.Open();
        cmd.CommandText = "select CategoryID from Categories";
        using (var reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                yield return reader.GetInt32(reader.GetOrdinal("CategoryID"));
            }
        }
    }
}

and then:

List<int> catIds = GetIds().ToList();
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • @Darim: While I like this code that would make it the responsibility of the consumer though to call `ToList()` - otherwise you have an open DB connection. I'm not convinced lazy is the right approach here. – BrokenGlass Apr 10 '11 at 17:09
  • 2
    @BrokenGlass no. the connection, the reader, all that stuff get closed once foreach is exited. Apart from the merit of this, a drawback would be that the caller will have to re-read the data from database if you have to re-use the objects in the IEnumerable and if you haven't stored all of them somewhere already. I mean in case you do not "foreach" fully. With `ToList()` you already have them somewhere.. – nawfal Feb 02 '13 at 18:09
  • `GetOrdnal` really is not necessary, especially where the query is a single column like this, `reader.GetOrdinal("CategoryID")` can just be replaced with `0` – Scott Chamberlain Aug 14 '13 at 04:40
  • Can we do it for List? – Jesuraja Jun 06 '14 at 09:54
3

Your current code should work, assuming catID is really declared before the try block, otherwise this won't compile.

BrokenGlass
  • 158,293
  • 28
  • 286
  • 335
  • catID is declared. When I test my code I only get back one CategoryID instead of four that I have in my table. – Erik Apr 10 '11 at 16:49
  • 2
    @Erik: Can you update your sample code with the *real* code you are running, you might be new-ing out the list every time, but above code is clearly not what you are using currently. – BrokenGlass Apr 10 '11 at 16:51
1

AS BrokenGlass explained this is the demonstration

SqlConnection connection = null;
        SqlDataReader dr= null;
        SqlCommand cmd = null;
List<int> catID = new List<int>();
        try
        {
            connection = new SqlConnection(connectionString);
            cmd = new SqlCommand("select CategoryID from Categories", connection );

            connection.Open();



            dr = cmd.ExecuteReader();
            while (dr.Read())
            {
                catID.Add(Convert.ToInt32(dr["CategoryID"].ToString()));
            }


        }
        finally
        {
            if (connection  != null)
                connection.Close();
        }
        return catID;

as well as you change the declaration

SqlDataReader reader = null;

to

SqlDataReader dr= null; // Because you are using dr in the code not reader
anishMarokey
  • 11,279
  • 2
  • 34
  • 47
0
        List<int> s = new List<int>();
        conn.Open();
        SqlCommand command2 = conn.CreateCommand();
        command2.CommandText = ("select turn from Vehicle where Pagged='YES'");
        command2.CommandType = CommandType.Text;
        SqlDataReader reader4 = command2.ExecuteReader();
        while (reader4.Read())
        {
            s.Add(Convert.ToInt32((reader4["turn"]).ToString()));
        }
        conn.Close();
Asanga
  • 1
0

This should work but I suggest you to use using with your connections

    SqlConnection connection = null;
    SqlDataReader reader = null;
    SqlCommand cmd = null;
    List<int> catID = new List<int>();
    try
    {
        connection = new SqlConnection(connectionString);
        cmd = new SqlCommand("select CategoryID from Categories", connection );

        connection.Open();



        dr = cmd.ExecuteReader();
        while (dr.Read())
        {   
            catID.Add(Convert.ToInt32(dr["CategoryID"].ToString()));
        }


    }
    finally
    {
        if (connection  != null)
            connection.Close();
    }
    return catID;
Bastardo
  • 4,144
  • 9
  • 41
  • 60