从方法返回datareader

我有以下方法

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。

谁能帮我吗

谢谢

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

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

 private IEnumerable GetRows(string sql, Action addParameters, Func 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 GetChildMenus(string url) { return GetRows("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( ... ); } } 

如https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand(v=vs.110).aspx中所示 :

  public static SqlDataReader ExecuteReader(String connectionString, String commandText, CommandType commandType, params SqlParameter[] parameters) { SqlConnection conn = new SqlConnection(connectionString); using (SqlCommand cmd = new SqlCommand(commandText, conn)) { cmd.CommandType = commandType; cmd.Parameters.AddRange(parameters); conn.Open(); // When using CommandBehavior.CloseConnection, the connection will be closed when the // IDataReader is closed. SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection); return reader; } } 

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

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