Breaking Change moving from 2.0 to 3.0

Topics: Data Access Application Block
May 22, 2007 at 9:10 PM
I have some code that calls ExecuteReader on a stored procedure and then iterates through the reader and builds up a collection of objects. The objects in the collection have an object property that was getting instanciated in its constructor - and to do this it was calling another stored procedure.

This code worked fine in v1.0 and v2.0 of the Ent Lib but when I moved to the ent lib v 3.0 it started to give me an error:

System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.

I changed the constructor so that is does not call out to the database when constructing each object - I am now lazy loading the object property I mentioned - better design anyways - and it fixed the error

what has changed in the entlib that might be causing this problem? Is it now trying to re-use connections?

My code has not changed in over a year.

thanks a lot
May 23, 2007 at 1:47 PM
Edited May 23, 2007 at 1:48 PM
In the previous version of the DAAB, a new connection was created each time you called one of the database methods unless you passed in an IDbTransaction.

In ADO.NET 2.0, we now have System.Transactions where you can use the TransactionScope Class to perform transactions:

using (TransactionScope scope = new TransactionScope(...))
    // Do Something

Unfortunately, because the DAAB always created new connections, this meant you would always get a distributed transaction when making multiple calls within TransactionScope.

To avoid this, the DAAB in Enterprise Library 3.0 now contains a class to keep track of connections so that if a current transaction is happening, it will reuse an existing connection to avoid opening a new one and causing a distributed transaction.

You might be experiencing this or a side-effect, but my thought is that this should only be happening when using System.Transactions.

I talk more about this here:

TransactionScope and Enterprise Library 3.0 Data Access Application Block - System.Transactions




David Hayden
Microsoft MVP C#
May 23, 2007 at 4:45 PM
Thanks for your response David.

So the thing I need to remember with EntLib DAAB 3.0 is if I am iterating through a data reader that calls other code that also creates a reader all within a transaction (I have code outside of this code that is calling it from within a transaction)- than I need to convert the outer reader(s) to something like a dataset.

Is this correct?

How about if I have code that uses a reader within a reader iteration but it is NOT in a transaction then it will not cause any problems?

May 23, 2007 at 6:06 PM
Hello...we are having an entLib issue that hopefully someone can help with....our team is writing an ASP.NET 2.0 application using the latest entLib. We are closing and disposing of the returned dataReader from an db.ExecuteReader call. We call the function again, and try to make the call again...

dataReader = db.ExecuteReader(System.Data.CommandType.Text, strSelect.ToString)

On this second call , we are receiving this error:

There is already an open DataReader associated with this Command which must be closed first.

Any ideas would be greatly appreciated... thanks, Mitch
May 23, 2007 at 6:27 PM
by the way.....MARS is not an option as we are using DB2...thanks, Mitch