我写了一个数据库操作类,其中有一个返回SqlDataReader的函数,可是在ASP.NET中调用出了问题.
数据库操作类相关函数:
        public SqlDataReader GetDataReader(string strSQL)
        {
            SqlConnection myCn = new SqlConnection(strConn);
            SqlCommand  sda = new SqlCommand(strSQL,myCn);
            try
            {
                myCn.Open();
                SqlDataReader dr = sda.ExecuteReader (CommandBehavior.Default);
                return dr;
            }
            catch (System.Data.SqlClient.SqlException e)
            {
                throw new Exception(e.Message);
            }
            finally
            {
                myCn.Close();
            }ASP.net页面调用代码:
<%     //DbBase是我定义的操作类.
       DbBase dbobj=new DbBase();
       //SqlDataReader dr = new SqlDataReader();
       SqlDataReader  dr = dbobj.GetDataReader("select * from Notice order by NoticeID");
       if (dr.Read())
       {
           Response.Write(dr[1].ToString());            
       }
       else
       {
           Response.Write("没有系统公告!");
       }
       dr.Dispose();
%>
结果一运行就出现下面的提示(我的数据库中是有数据的):Invalid attempt to Read when reader is closed. 
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details: System.InvalidOperationException: Invalid attempt to Read when reader is closed.Source Error: 
Line 8:         //SqlDataReader dr = new SqlDataReader();
Line 9:         SqlDataReader  dr = dbobj.GetDataReader("select * from Notice order by NoticeID");
Line 10:        if (dr.Read())  //此处是红色!!!!!!!!!!!!!!!!!!!!!!!
Line 11:        {
Line 12:            Response.Write(dr[1].ToString());            
请有经验的大侠指点一下,着急!~

解决方案 »

  1.   

    SqlConnection myCn = new SqlConnection(strConn);
                SqlCommand  sda = new SqlCommand(strSQL,myCn);
                try
                {
                    myCn.Open();
                    SqlDataReader dr = sda.ExecuteReader (CommandBehavior.CloseConnection);
                    return dr;
                }
                catch (System.Data.SqlClient.SqlException e)
                {
                    throw new Exception(e.Message);
                }
      

  2.   

    <%     //DbBase是我定义的操作类.
           DbBase dbobj=new DbBase();
           //SqlDataReader dr = new SqlDataReader();
           SqlDataReader  dr = dbobj.GetDataReader("select * from Notice order by NoticeID");
           if (dr.Read())
           {
               Response.Write(dr[1].ToString());            
           }
           else
           {
               Response.Write("没有系统公告!");
           }
           dr.Close();
    %>
      

  3.   

    还是不行!我是操作类,返回Datareader对象,CommandBehavior.CloseConnection这个属性设置好象没用,我刚才试过了,Lcindep110(影子)的方法更不行了,我都没打开,close根本没有用.
      

  4.   

    楼主的思路有问题。请看你的代码
      public SqlDataReader GetDataReader(string strSQL)
            {
                SqlConnection myCn = new SqlConnection(strConn);
                SqlCommand  sda = new SqlCommand(strSQL,myCn);
                try
                {
                    myCn.Open();
                    SqlDataReader dr = sda.ExecuteReader (CommandBehavior.Default);
                    return dr;  //在此位置已经retrn
                }
                catch (System.Data.SqlClient.SqlException e)
                {
                    throw new Exception(e.Message);
                }
                finally
                {
                    myCn.Close();  //后面连接已关闭
                }当你在CS页中通过dr.read的时候你的返回值里面根本没有数据!!所以就读不到
    要知道datareader是单向单条只读的 //特别注意是单向单条。不是所有的数据解决方法:
    将你的
       if (dr.Read())
           {
               Response.Write(dr[1].ToString());            
           }
           else
           {
               Response.Write("没有系统公告!");
           }
           dr.Dispose();
    这段代码封装到类中。
    方法二
    类的返回类型不要用datareader,考虑用数组或另外设置专门接受对象的类来接收返回数据
      

  5.   

    问题是:我在网上找到了无数个封装好的数据库操作类,里面都有返回SqlDataReader类型的函数,楼上的意思也有道理.问题是,写类的作用就是要保证通用行,所以你的第一个建议也是不符合设计原则的.第二条建议也可以,但是我觉得不应该那么麻烦,问题应该出在返回过程中。
      

  6.   


     finally
    {
    myCn.Close();
    }

    dr.Dispose();
    都去掉试试
      

  7.   

    kbxj406(羽儿):正解,通过测试,不过为什么呢?这样我的类方法就不能关闭连接对象了!!
      

  8.   

    SqlDataReader  dr = dbobj.GetDataReader("select * from Notice order by NoticeID");
    if (dr.Read())
    {
    Response.Write(dr[1].ToString());            
    }由于SqlDataReader是一行一行读的,如果加了dr.Dispose();后,读了一行后,dr对象就被释放掉了,但从数据方面考虑,dr还需要继续遍历,当第二次返回的时候就会出错了。思路:
    你可以把dr定义在外层,然后if遍历完后再Dispose();掉:
    SqlDataReader  dr = new SqlDataReader();
    dr = dbobj.GetDataReader("select * from Notice order by NoticeID");
           if (dr.Read())
           {
               Response.Write(dr[1].ToString());            
           }
           else
           {
               Response.Write("没有系统公告!");
           }
    dr.Dispose();
    看行不行
      

  9.   

    SqlDataReader dr = new SqlDataReader( );这样不行啊,根本通过不了.
    sqldatareader 对象好象必须通过command对象返回.
      

  10.   

    你们一定没看出来,原来我在类里和asp页面里都用sqldatareader dr=.......
      

  11.   

    ====ExecuteReader(CommandBehavior)========CloseConnection 在执行该命令时,如果关闭关联的 DataReader 对象,则关联的 Connection 对象也将关闭。  
     Default 此查询可能返回多个结果集。执行查询可能会影响数据库状态。Default 不设置 CommandBehavior 标志,因此调用 ExecuteReader(CommandBehavior.Default) 在功能上等效于调用 ExecuteReader()。  
     KeyInfo 此查询返回列和主键信息。  
    当 KeyInfo 用于命令执行时,提供程序将为现有主键列和时间戳列的结果集附加额外的列。 当使用 KeyInfo 时,用于 SQL Server 的 .NET Framework 数据提供程序将在要执行的语句前加上 SET FMTONLY OFF 和 SET NO_BROWSETABLE ON。用户应该注意潜在的副作用,例如对 SET FMTONLY ON 语句的使用产生的干扰。有关更多信息,请参见“SQL Server 联机丛书”。
     
     SchemaOnly 查询仅返回列信息。当使用 SchemaOnly 时,用于 SQL Server 的 .NET Framework 数据提供程序将在要执行的语句前加上 SET FMTONLY ON。  
     SequentialAccess 提供一种方法,以便 DataReader 处理包含带有大二进制值的列的行。SequentialAccess 不是加载整行,而是使 DataReader 将数据作为流来加载。然后可以使用 GetBytes 或 GetChars 方法来指定开始读取操作的字节位置以及正在返回的数据的有限的缓冲区大小。 
    当指定 SequentialAccess 时,尽管无需读取每个列,但是需要按照列的返回顺序读取它们。一旦已经读过返回的数据流中某个位置的内容,就不能再从 DataReader 中读取该位置或该位置之前的数据。当使用 OleDbDataReader 时,可重新读取当前列的值,直到读过它。当使用 SqlDataReader 时,一次只能读取一个列值。
     
     SingleResult 查询返回一个结果集。  
     SingleRow 查询应返回一行。执行查询可能会影响数据库的状态。一些 .NET Framework 数据提供程序可能(但不要求)使用此信息来优化命令的性能。用 OleDbCommand 对象的 ExecuteReader 方法指定 SingleRow 时,用于 OLE DB 的 .NET Framework 数据提供程序使用 OLE DB IRow 接口(如果可用)执行绑定。否则,它使用 IRowset 接口。如果您的 SQL 语句应该只返回一行,则指定 SingleRow 还可以提高应用程序性能。在执行返回多个结果集的查询时,可以指定 SingleRow。在这种情况下,仍返回多个结果集,但每个结果集只有一行。  所以你conn.open
    sda.ExecuteReader (CommandBehavior.Default);
    conn.close
    时连接和sqldatareader都已同时关闭
    经常见到的解决方法如jc15271149(嘿咻)所示
    conn.open()
    sda.ExecuteReader (CommandBehavior.CloseConnection);
    然后不关闭连接
    而是在aspx中关闭sqldatareader
    这样就可以了