从方法返回datareader

时间:2013-11-22 14:17:11

标签: c# asp.net

我有以下方法

    public static SqlDataReader MenuDataReader(string url)
    {
        using (SqlConnection con = new SqlConnection(connectionString))
        {
            using (SqlCommand cmd = new SqlCommand("spR_GetChildMenus", con))
            {
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.AddWithValue("@PageUrl", url);
                cmd.Parameters.AddWithValue("@MenuId", ParameterDirection.Output);
                cmd.Parameters.AddWithValue("@ParentId", ParameterDirection.Output);
                cmd.Parameters.AddWithValue("@TitleText", ParameterDirection.Output);
                cmd.Parameters.AddWithValue("@ExternalUrl", ParameterDirection.Output);
                cmd.Parameters.AddWithValue("@FullUrl", ParameterDirection.Output);
                cmd.Parameters.AddWithValue("@ChildCount", ParameterDirection.Output);
                con.Open();
                SqlDataReader reader = cmd.ExecuteReader();
                if (reader.HasRows)
                {
                    //return reader;

                    while (reader.Read())
                    {
                        return reader;
                    }

                }
            }
        }
        return null;
    }

我这样称呼

        SqlDataReader reader = MenuDataReader(url);
        if (reader.HasRows)
        {
            while (reader.Read())
            { }}

然而我收到错误消息

  

关闭阅读器时无效尝试调用HasRows。

任何人都可以帮助我

感谢

4 个答案:

答案 0 :(得分:14)

答案 1 :(得分:11)

你真的需要读者,还是只需要某种方法来迭代它里面的行?我建议使用迭代器块。您可以在源方法中迭代您的行,并且每行依次yield给调用者。

这种技术有一个转折:因为你在每次迭代时都会产生相同的对象,所以有些情况会导致问题,所以你最好还要求委托将某行的内容复制到某处。我还想将它抽象为可用于任何查询的泛型方法,并使用相同的委托技术来处理参数数据,如下所示:

private IEnumerable<T> GetRows<T>(string sql, Action<SqlParameterCollection> addParameters, Func<IDataRecord, T> copyRow)
{
     using (var cn = new SqlConnection("Connection string here"))
     using (var cmd = new SqlCommand(sql, cn)
     {
         cmd.CommandType = CommandType.StoredProcedure;
         addParameters(cmd.Parameters);
         cn.Open();
         using (var rdr = cmd.ExecuteReader())
         {
             while (rdr.Read())
             {
                 yield return copyRow(rdr);
             }
             rdr.Close();
         }
     }
}

public IEnumerable<MenuItem> GetChildMenus(string url)
{
     return GetRows<MenuItem>("spR_GetChildMenus", p =>
     {
         //these lines are copied from your question, but they're almost certainly wrong
         p.AddWithValue("@PageUrl", url);
         p.AddWithValue("@MenuId", ParameterDirection.Output);
         p.AddWithValue("@ParentId", ParameterDirection.Output);
         p.AddWithValue("@TitleText", ParameterDirection.Output);
         p.AddWithValue("@ExternalUrl", ParameterDirection.Output);
         p.AddWithValue("@FullUrl", ParameterDirection.Output);
         p.AddWithValue("@ChildCount", ParameterDirection.Output);
     }, r =>
     {
         return new MenuItem( ... );
     }
 }

答案 2 :(得分:4)

我不会返回读者 - 您的连接和命令的Dispose正在关闭连接。我会返回一个代表性的数据模型。

答案 3 :(得分:1)

当您在using语句中返回时,代码会在Dispose上调用SqlConnection。这会关闭DataReader,从而导致错误。