pleaes help, Invalid attempt to call FieldCount when reader is closed

Topics: Data Access Application Block
Feb 9, 2011 at 3:28 AM
Edited Feb 9, 2011 at 3:28 AM

 

here's my code, those that commented out are the codes I have originally.  it's not working, i cannot cast IDataREader to SqlDataReader.  
I followed the instruction in this post. http://entlib.codeplex.com/Thread/View.aspx?ThreadId=211288

it fixed it. but everytime I run my application, I m getting this error message. "Invalid attempt to call FieldCount when reader is closed"
 spending hrs searching on google, coudln't find anything helpful. please help me.




public SqlDataReader GetHospitals() { //using (IDataReader dr = _db.ExecuteReader("GetHospitals")) //{ // return (SqlDataReader)dr; //} using (RefCountingDataReader dr = (RefCountingDataReader)_db.ExecuteReader("GetHospitals")) { return (SqlDataReader)dr.InnerReader; } }

 

 

here's my gridview, I bind  gridview using dataobjectsource.

 

 

<%@ Page Title="" Language="C#" MasterPageFile="~/site.Master" AutoEventWireup="true"
    CodeBehind="default.aspx.cs" Inherits="cHospital._default" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
    welcome,
    <asp:Label ID="lblName" runat="server" Text=""></asp:Label>
    <asp:ObjectDataSource ID="odsHospitalList" runat="server" SelectMethod="GetHospitals"
        TypeName="cHospital.Hospital"></asp:ObjectDataSource>
    <asp:GridView ID="gvHospital" runat="server" DataSourceID="odsHospitalList" EnableModelValidation="True"
        AutoGenerateSelectButton="false" AutoGenerateDeleteButton="false" DataKeyNames="taxID"
        CssClass="mGrid" AutoGenerateColumns="false" Width="700px">
        <Columns>
            <asp:BoundField DataField="hospitalName" HeaderText="Hospital Name" />
            <asp:BoundField DataField="taxID" HeaderText="Tax ID" />
            <asp:BoundField DataField="address1" HeaderText="Address 1" />
            <asp:BoundField DataField="address2" HeaderText="Address 2" />
            <asp:BoundField DataField="city" HeaderText="City" />
            <asp:BoundField DataField="state" HeaderText="State" />
            <asp:BoundField DataField="zip" HeaderText="Zip" />
            <asp:CommandField ShowSelectButton="True" ItemStyle-CssClass="cmdSelect" ItemStyle-Width="50px" />
            <asp:CommandField ShowDeleteButton="True" ItemStyle-CssClass="cmdSelect" ItemStyle-Width="50px" />
        </Columns>
        <EmptyDataTemplate>
            No records found!
        </EmptyDataTemplate>
    </asp:GridView>
</asp:Content>

 

Feb 9, 2011 at 4:11 AM
Edited Feb 9, 2011 at 4:42 AM

It seems the using statement automatically closed the reader after you returned the sqldatareader.  Check the IsClosed property to verify.  In addition, you shouldn't be returning the inner reader and leave the outer reader as it will cause connection leaks.  As suggested in the post you read, create an extension method for it.

public SqlDataReader AsSqlDataReader(this IDataReader dataReader)
{
           return (SqlDataReader)((RefCountingDataReader)reader).InnerReader;
}

so that whenever you call db.ExecuteReader, you'll only need to do this to obtain an instance of SqlDataReader:

using(IDataReader reader = db.ExecuteReader("GetHospitals"))
{
        SqlDataReader sqlReader = reader.AsSqlDataReader();
}


 

Sarah Urmeneta
Global Technologies and Solutions
Avanade, Inc.
entlib.support@avanade.com

Feb 9, 2011 at 4:55 AM

Sarah, thank you so much for your help.  I still couldn't get it work.  Same Error message.  my page  actually very simple.

I only have one gridviews, one  objectdatasource.  if you have time, please take a look at my code. 


here's my code.  this is  datareaderextensions file

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;  

namespace cHospital
{
    public static class DataReaderExtensions
    {
        public static SqlDataReader CastDR (this IDataReader dataReader)
        {
            return (SqlDataReader)((RefCountingDataReader)dataReader).InnerReader;
        }
    }
}

 

 

here's my class file

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using System.Web.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;


namespace cHospital
{
    public class Hospital
    {
        private Database _db = EnterpriseLibraryContainer.Current.GetInstance<Database>("Conn");

        public Hospital()
        {

        }


        public SqlDataReader GetHospitals()
        {

            SqlDataReader sqlReader;

            using (RefCountingDataReader dr = (RefCountingDataReader)_db.ExecuteReader("GetHospitals"))
            {
                sqlReader = dr.CastDR();
         
            }

            return sqlReader;
        }

    }
}

 

here's my default.aspx file

<%@ Page Title="" Language="C#" MasterPageFile="~/site.Master" AutoEventWireup="true"
    CodeBehind="default.aspx.cs" Inherits="cHospital._default" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
    welcome,
    <asp:Label ID="lblName" runat="server" Text=""></asp:Label>
    <asp:ObjectDataSource ID="odsHospitalList" runat="server" SelectMethod="GetHospitals"
        TypeName="cHospital.Hospital"></asp:ObjectDataSource>
    <asp:GridView ID="gvHospital" runat="server" DataSourceID="odsHospitalList" EnableModelValidation="True"
        AutoGenerateSelectButton="false" AutoGenerateDeleteButton="false" DataKeyNames="taxID"
        CssClass="mGrid" AutoGenerateColumns="true" Width="700px">
 
    </asp:GridView>
</asp:Content>

 

 

Feb 9, 2011 at 5:12 AM

It still doesn't work because of the same reason, the SqlDataReader was closed after you returned it.  You should return the IDataReader, perform the casting to SqlDataReader in the aspx codebehind file:

public IDataReader GetHospitals()
{
            return  db.ExecuteReader("GetHospitals"))
}


In your code behind file:

using(IDataReader reader = GetHospitals())
{
            SqlDataReader sqlReader = reader.AsSqlReader();
            ///perform binding
}

Sarah Urmeneta
Global Technologies and Solutions
Avanade, Inc.
entlib.support@avanade.com

Feb 9, 2011 at 12:14 PM

you are right.  if I have following codes in codebehind, it works.

 

           using (RefCountingDataReader dr = (RefCountingDataReader)_db.ExecuteReader("GetHospitals"))
            {
                this.gvHospital.DataSource = (SqlDataReader)dr.InnerReader;
                this.gvHospital.DataBind();
            }

 

here's the problem,  those codes have to stay in  Hospital.cs file because I am using ObjectDataSources  ( maybe I am wrong,  I am still new to .net ).

Feb 10, 2011 at 7:12 AM

Please see thread http://entlib.codeplex.com/Thread/View.aspx?ThreadId=245335 for our response :)

Gino Terrado
Global Technologies and Solutions
Avanade, Inc.
entlib.support@avanade.com