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
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.
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
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()) {} )
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.
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
> 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.
Copyright (c) Marimer LLC