C# 从方法返回datareader
我有以下方法C# 从方法返回datareader,c#,asp.net,C#,Asp.net,我有以下方法 public static SqlDataReader MenuDataReader(string url) { using (SqlConnection con = new SqlConnection(connectionString)) { using (SqlCommand cmd = new SqlCommand("spR_GetChildMenus", con)) {
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的尝试无效
有人能帮我吗
谢谢我不会返回读卡器-您连接的
Dispose
命令正在关闭连接。相反,我将返回数据的代表性模型。当您使用语句返回内部时,代码调用SqlConnection上的Dispose
。这将关闭数据读取器,从而导致错误。您真的需要读取器,还是只需要某种方法来遍历其中的行?我建议使用迭代器块。您可以在源方法内迭代您的行,然后依次向调用者产生每一行
这种技术有一个转折点:因为每次迭代都会产生相同的对象,所以在某些情况下,这可能会导致问题,因此最好也让代理将行的内容复制到某个地方。我还想将其抽象为可用于任何查询的通用方法,并使用相同的委托技术处理参数数据,如下所示:
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( ... );
}
}
private IEnumerable GetRows(字符串sql、操作addParameters、Func copyRow)
{
使用(var cn=new-SqlConnection(“此处为连接字符串”))
使用(var cmd=new SqlCommand(sql,cn)
{
cmd.CommandType=CommandType.storedProcess;
addParameters(命令参数);
cn.Open();
使用(var rdr=cmd.ExecuteReader())
{
while(rdr.Read())
{
收益返回复写行(rdr);
}
rdr.Close();
}
}
}
公共IEnumerable GetChildMenus(字符串url)
{
返回GetRows(“spR_GetChildMenus”,p=>
{
//这些台词是从你的问题中抄来的,但它们几乎肯定是错的
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=>
{
返回新的菜单项(…);
}
}
如图所示:
有没有关于如何操作的线索?您可以从函数返回读取器,但前提是您将连接对象作为参数传递给它。您可以使用“CommandBehavior.CloseConnection”选项创建读取器,以便在读取器关闭时自动关闭。必须找到一种很难的方法:当您在while(reader.Read())中时
构造您的对象,然后返回一个列表
@Ric,这有点违背了使用datareader的目的。您并不比Fill()好多少-此时正在删除数据集。有一些方法可以保留DataReader每次一条记录的特性。当然可以,但是如果处理了连接,那么您的命令将导致执行某些操作,而不是返回读取器。这就是我从这个答案中得到的,也是我将要做的,返回强类型对象etcAre你确定它不返回Null?为什么要返回阅读器?我已经修改为“abbas”当读卡器关闭时,调用HasRows的尝试无效。所以我想我需要更改it@andrewslaughter读卡器依赖于SqlConnection。当您退出using语句时,SqlConnection将关闭,此后您将无法使用读卡器。我将同意Daniel A White的建议,阅读您的rea在退出该方法之前删除。或者将一个SqlConnection传递到该方法中,这样它就不会像Yuriy Galanter建议的那样关闭。这是我最喜欢的解决方案。这是一个非常好的答案。您可以更进一步,使一切IDataReader
,IDbCommand
,IDbConnection
,以及DbParameter
,re移动Sql依赖项。您将传递Func dbConnectionFactory
,而不是连接字符串,这是一个创建所需连接的函数。然后,您是否需要确保在返回的读取器周围实现using语句,以确保其正确关闭?连接是否保持打开状态?@TylerNielsen-t中的示例这个链接显示了包装在using语句中的返回的读卡器。请看GetDepartments()函数。在一个特殊的情况下,您真正想要返回读卡器的是在一个单独的数据库中进行批量插入,该数据库有自己的连接。
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;
}
}