CSLA .NET

Vibrant discussion about CSLA .NET and using the framework to build great business applications.

Repository pattern (Demo DpRepos) - Invalid attempt to call Read when reader is closed

rated by 0 users
Answered (Verified) This post has 1 verified answer | 6 Replies | 3 Followers

Top 500 Contributor
26 Posts
cconte posted on Tue, Jan 17 2012 8:00 AM

Hi All,

I'm currently working on de DpREPOS from the CSLA Core video series to learn how manipulate the DataAccess.

Actually, im focusing on the Repository pattern, using DataPortal_XYZ methods (EncapsulatedInvoke data reader)

So, I have reproduced a small demo where the structure is almost identical to the structure in the DpRepos example of the 3.8 demos.

but when i run my Demo I get the following error "Invalid attempt to call Read when reader is closed"  when the DataPortal_Fetch try to read the IDataReader provide by the DAL.

It's like if the  IdataReader  return by he DAL cannot keep data cause the connection reader or database is closed ?

Some of the things I’ve tried and checked
- The SQL request is correct and return data
- Added the option "MultipleActiveResultSets=True" to my connection string

see Below the code :

namespace DataAccess.MsSQL
{
    public class ProductEditDal : DataAccess.IProductEditDal
    {

        public IDataReader Fetch()
        {
            using (var ctx = ConnectionManager<SqlConnection>.GetManager("LioDB"))
            {
                using (var cm = ctx.Connection.CreateCommand())
                {
                    cm.CommandType = System.Data.CommandType.Text;
                    cm.CommandText = "SELECT ProductID, Name FROM Product";
                    return cm.ExecuteReader();
                }
            }
        }
...
}


namespace Library
{
    public partial class ProductEdit
    {

        #region Data

        private void DataPortal_Fetch(SingleCriteria<ProductEdit, int> criteria)
        {
            using (var dalFactory = DataAccess.DalFactory.GetManager())
            {
                var dal = dalFactory.GetProvider<DataAccess.IProductEditDal>();
                using (var dr = new SafeDataReader(dal.Fetch(criteria.Value)))
                {
                    // Here i get an Execption =>  Invalid attempt to call Read when reader is closed.  
                     dr.Read();
                    using (BypassPropertyChecks)
                    {
                        ProductID = dr.GetInt32("ProductID");
                        Name = dr.GetString("Name");
                    }
                }
            }

I appreciate any suggestions anyone can offer.

Thanks in advance for your help,

Cedric

Answered (Verified) Verified Answer

Top 10 Contributor
2,173 Posts
Verified by cconte

Hi,

You are NOT using the repository pattern if you return an IDataReader.

You should return an object with the values retrieved from the database and not an IDataReader.!!

           using (var ctx = ConnectionManager<SqlConnection>.GetManager("LioDB"))
            {
                using (var cm = ctx.Connection.CreateCommand())
                {
                    cm.CommandType = System.Data.CommandType.Text;
                    cm.CommandText = "SELECT ProductID, Name FROM Product";
                    return cm.ExecuteReader();
                }
            }

Using is translated in compiled code to

try
     -- execute statements
finally
    -- dispose object

so when you use using (var conn...... ) the connection will be closed when it leaves the scope. Hence your connection is closed before the method returns.

Your ProductEditDal should be created and the values (Id, Name) set inside the using block.
Fetch method should return an object of type ProductEditDal.

Jonny Bekkum, Norway CslaContrib Coordinator

All Replies

Top 10 Contributor
2,173 Posts
Verified by cconte

Hi,

You are NOT using the repository pattern if you return an IDataReader.

You should return an object with the values retrieved from the database and not an IDataReader.!!

           using (var ctx = ConnectionManager<SqlConnection>.GetManager("LioDB"))
            {
                using (var cm = ctx.Connection.CreateCommand())
                {
                    cm.CommandType = System.Data.CommandType.Text;
                    cm.CommandText = "SELECT ProductID, Name FROM Product";
                    return cm.ExecuteReader();
                }
            }

Using is translated in compiled code to

try
     -- execute statements
finally
    -- dispose object

so when you use using (var conn...... ) the connection will be closed when it leaves the scope. Hence your connection is closed before the method returns.

Your ProductEditDal should be created and the values (Id, Name) set inside the using block.
Fetch method should return an object of type ProductEditDal.

Jonny Bekkum, Norway CslaContrib Coordinator

Top 500 Contributor
26 Posts
cconte replied on Tue, Jan 17 2012 8:45 AM

Hi JonnyBee,

My mistake, I'm using the EncapsulatedInvoke technique (DP_XYZ invoking DAL).

Actually, I have just found what i'm doing wrong , the DalManager was not well implement cause the Database connection was not persistent.

And like you said in the previous mail, my data reader was closed  before the method returns

Thx again for your help,

Cedric

Not Ranked
5 Posts
sguolla replied on Wed, Feb 15 2012 11:44 AM

We're running into the exact same problem.  What exactly was the solution?  We have this code in our DAL:

 

 

 

 

 

 

using

 

 

(var ctx = ConnectionManager<SqlConnection>.GetManager("LocalDb"))

{

 

var cmd = ctx.Connection.CreateCommand();

cmd.CommandType =

 

CommandType.StoredProcedure;

cmd.CommandText =

 

"up_HarbingerPatientListOf";

cmd.Parameters.AddWithValue(

 

"@FacilityId", facilityId);

 

 

 

return cmd.ExecuteReader();}

Then we fail when we try to read from IDataReader (e.g. while (data.Read()) {} )

 

Top 10 Contributor
2,173 Posts

hi,

Read the part in my previous answer on what using is translated to by the compiler.

If you need to return an open reader you should not use using on your data access. 

Jonny Bekkum, Norway CslaContrib Coordinator

Not Ranked
5 Posts

Hi JonnyBee,

Thanks for the quick response.  We figured out our problem.  We were missing some code snippets in our DalManager class.  We zipped through things quickly yesterday without fully reading everything in our e-book.

Stewart G

Denver, CO

Top 10 Contributor
9,413 Posts

> You are NOT using the repository pattern if you return an IDataReader.

That's not necessarily true. Your provider interface could be based on IDataReader - I do this in the Data Access book.

The thing with building a DAL interface based on IDataReader is that you have to fully understand how data readers and connections work, and live within those constraints.

Rocky

Page 1 of 1 (7 items) | RSS

Copyright (c) 2006-2014 Marimer LLC. All rights reserved.
Email admin@lhotka.net for support.
Powered by Community Server (Non-Commercial Edition), by Telligent Systems