C# - 从SqlDataReader中填充泛型列表

12
我该如何将 SqlDataReader 返回的值添加到泛型列表中?我有一个方法使用 SqlDataReaderCategory 表中获取 CategoryID。我想将所有CategoryID 添加到一个泛型列表中。
这种方式不起作用,因为它只返回一个categoryID,即最后一个。 我想将所有的categoryID 添加到列表中,然后返回它们。
我该如何做到这一点?
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;

你有一个名为 catId字段 吗? - SLaks
在连接、命令和读取器周围使用using语句! - RQDQ
5个回答

15

试着这样做,它更好、更安全、使用惰性加载、代码更少、可行......:

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"));
            }
        }
    }
}

接下来:

List<int> catIds = GetIds().ToList();

@Darim:虽然我喜欢这段代码,但这将使消费者调用 ToList() 成为责任 - 否则您将拥有一个打开的数据库连接。我不确定懒惰是正确的方法。 - BrokenGlass
2
@BrokenGlass 不会。连接,读取器和所有相关内容都会在foreach退出时关闭。除了这个好处之外,缺点是如果您必须重新使用IEnumerable中的对象并且尚未将它们全部存储在某个地方,则调用者将不得不从数据库重新读取数据。我的意思是,如果您没有完全执行“ foreach”,则需要这样做。使用 ToList() 就已经可以将它们存在某个地方了。 - nawfal
“GetOrdnal” 确实不是必要的,特别是在查询只有一个列的情况下,像这样 reader.GetOrdinal("CategoryID") 可以直接替换为 0 - Scott Chamberlain
我们可以为 List<T> 做这件事吗? - Jesuraja

3

假设catID在try块之前已经声明,那么您当前的代码应该可以正常工作,否则这将无法编译。


catID已经声明。当我测试我的代码时,我只得到了一个CategoryID,而不是我在表中有四个。 - Erik
2
@Erik:你能否更新你的示例代码,使用你正在运行的真实代码?你可能每次都在新建列表,但上面的代码显然不是你当前正在使用的代码。 - BrokenGlass

1

正如BrokenGlass所解释的那样,这是一个演示

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;

同时你也需要改变声明

SqlDataReader reader = null;

SqlDataReader dr= null; // Because you are using dr in the code not reader

0

这应该可以工作,但我建议您在connections中使用using

    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;

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();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接