[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

8870

3/15/2005 11:29:00 AM

I hope the next release of the .net framework will allow multiple active
DataReaders for ALL connection types (sqlserver, oledb, odbc).
The version I have (1.1.4322) does not. I cannot understand the reason for
this limitation (see exception in the following code)
as the underlying technology, in this case ODBC, doesn't have this limitation.
The following example is of no use, but it shows the problem.

using System;
using System.Data;
using System.Data.OleDb;
using System.Data.Odbc;

public class test{
public static void Main(String[] args){
IDbConnection conn = new OdbcConnection("DSN=...");
conn.Open();

IDbCommand cmd1 = conn.CreateCommand();
cmd1.CommandText="SELECT tabname from systables";

IDataReader rdr1 = cmd1.ExecuteReader();
//rdr1.Close();

IDbCommand cmd2 = conn.CreateCommand();
cmd2.CommandText="SELECT idxname from sysindexes";
IDataReader rdr2 = cmd2.ExecuteReader();
/////////////
//// Unhandled Exception: System.InvalidOperationException: There is
already an open
//// DataReader associated with this Connection which must be closed first.
/////////////

while(rdr1.Read()) Console.WriteLine(rdr1.GetString(0));

for(int i=0; i<10; i++){
rdr1.Read(); Console.WriteLine(rdr1.GetString(0));
rdr2.Read(); Console.WriteLine(rdr2.GetString(0));
}

}
}
7 Answers

8870

3/15/2005 11:39:00 AM

0

the line "while(rdr1.Read()) Console.WriteLine(rdr1.GetString(0));" should
not be there, and of course I should check for eof. But the problem occurs
when calling cmd2.ExecuteReader()

Sylvain Lafontaine

3/19/2005 7:08:00 AM

0

The ODBC and the OLEDB drivers doesn''t permit to have multiple concurrent
streams opened from the same connection. What''s happening is that these
drivers will open a second anonymous connection when required, giving you
the impression that a single connection is handling multiple stream.
However it''s easy to see that this leads to a lot of problems/bugs when
transactions and other specific features linked to connections (like
temporary tables) are involved (for example because a transaction is always
associated with a single connection and that other connections, including
anonymous connections, cannot be part of it).

These "under the hood" features has been removed from the .NET framework and
if I were you, I wouldn''t hope to much on seeing them in the next release.
If you need two open connections, then all you have to do is to open two
connections; no mess, no fuss.

S. L.

"8870" <8870@discussions.microsoft.com> wrote in message
news:6E97D94C-9D8E-4DB7-95D2-466D4672FE23@microsoft.com...
>I hope the next release of the .net framework will allow multiple active
> DataReaders for ALL connection types (sqlserver, oledb, odbc).
> The version I have (1.1.4322) does not. I cannot understand the reason for
> this limitation (see exception in the following code)
> as the underlying technology, in this case ODBC, doesn''t have this
> limitation.
> The following example is of no use, but it shows the problem.
>
> using System;
> using System.Data;
> using System.Data.OleDb;
> using System.Data.Odbc;
>
> public class test{
> public static void Main(String[] args){
> IDbConnection conn = new OdbcConnection("DSN=...");
> conn.Open();
>
> IDbCommand cmd1 = conn.CreateCommand();
> cmd1.CommandText="SELECT tabname from systables";
>
> IDataReader rdr1 = cmd1.ExecuteReader();
> //rdr1.Close();
>
> IDbCommand cmd2 = conn.CreateCommand();
> cmd2.CommandText="SELECT idxname from sysindexes";
> IDataReader rdr2 = cmd2.ExecuteReader();
> /////////////
> //// Unhandled Exception: System.InvalidOperationException: There is
> already an open
> //// DataReader associated with this Connection which must be closed
> first.
> /////////////
>
> while(rdr1.Read()) Console.WriteLine(rdr1.GetString(0));
>
> for(int i=0; i<10; i++){
> rdr1.Read(); Console.WriteLine(rdr1.GetString(0));
> rdr2.Read(); Console.WriteLine(rdr2.GetString(0));
> }
>
> }
> }


8870

3/21/2005 12:11:00 PM

0

Thank you for the detailed answer. I don''t know OLEDB, but have tried with
ODBC to an informix database (using the current version of the informix ODBC
driver) and it definitely doesn''t open more than 1 connection in order to
fetch the data from the 2 SQL statements. The number of records in both
tables was large enough so that it had to read records alternately from the 2
statements several times. At no time there were more than one IP connection
to the database server. I have verified that on the client (netstat) and on
the server (db monitoring tool). A network sniffer has shown that records
from both statements have alternately gone over the network.
The SQLFetch function of the ODBC API has a parameter hStmt so the API
should allow multiple streams; maybe as you wrote some ODBC drivers do really
open more connections for providing the desired functionality. Whether more
connections are created seems to depend on the driver.
I agree that more connections is a bad choice; however as OdbcConnection has
the limitation mentioned, you are forced to use them, if you don''t want to
store the entire result set (which can sometimes be large) in the DataTable
(that is in the RAM of the client) if you need other SQL statements while the
result from the first one has not yet been entirely fetched by the client (by
IDataReader.Read()).

"Sylvain Lafontaine" wrote:
> The ODBC and the OLEDB drivers doesn''t permit to have multiple concurrent
> streams opened from the same connection. What''s happening is that these
> drivers will open a second anonymous connection when required, giving you
> the impression that a single connection is handling multiple stream.
> However it''s easy to see that this leads to a lot of problems/bugs when
> transactions and other specific features linked to connections (like
> temporary tables) are involved (for example because a transaction is always
> associated with a single connection and that other connections, including
> anonymous connections, cannot be part of it).
>
> These "under the hood" features has been removed from the .NET framework and
> if I were you, I wouldn''t hope to much on seeing them in the next release.
> If you need two open connections, then all you have to do is to open two
> connections; no mess, no fuss.

Sylvain Lafontaine

3/21/2005 11:44:00 PM

0

Well, I don''t know about the informix ODBC driver and what''s the exact
definition of an OdbcConnection. (Does a second connection necessarily
involve a second TCP/IP connection?). Maybe you will find more information
on dedicated references for ODBC and OLEDB.

All I can tell you is that it has been explicitely removed by Microsoft on
its native NET drivers for JET and SQL-Server because of the numerous bugs
that this feature has introduced in the past on complex situations. Maybe
other .NET providers - from Informix or Orable for example - will provide it
or maybe even MS will change its decision in the futur but for now, this is
*out* and it''s not by inadvertence.

S. L.

"8870" <8870@discussions.microsoft.com> wrote in message
news:453E885E-E7D1-4B3D-BBD1-5EFD63C4D20D@microsoft.com...
> Thank you for the detailed answer. I don''t know OLEDB, but have tried with
> ODBC to an informix database (using the current version of the informix
> ODBC
> driver) and it definitely doesn''t open more than 1 connection in order to
> fetch the data from the 2 SQL statements. The number of records in both
> tables was large enough so that it had to read records alternately from
> the 2
> statements several times. At no time there were more than one IP
> connection
> to the database server. I have verified that on the client (netstat) and
> on
> the server (db monitoring tool). A network sniffer has shown that records
> from both statements have alternately gone over the network.
> The SQLFetch function of the ODBC API has a parameter hStmt so the API
> should allow multiple streams; maybe as you wrote some ODBC drivers do
> really
> open more connections for providing the desired functionality. Whether
> more
> connections are created seems to depend on the driver.
> I agree that more connections is a bad choice; however as OdbcConnection
> has
> the limitation mentioned, you are forced to use them, if you don''t want to
> store the entire result set (which can sometimes be large) in the
> DataTable
> (that is in the RAM of the client) if you need other SQL statements while
> the
> result from the first one has not yet been entirely fetched by the client
> (by
> IDataReader.Read()).
>
> "Sylvain Lafontaine" wrote:
>> The ODBC and the OLEDB drivers doesn''t permit to have multiple concurrent
>> streams opened from the same connection. What''s happening is that these
>> drivers will open a second anonymous connection when required, giving you
>> the impression that a single connection is handling multiple stream.
>> However it''s easy to see that this leads to a lot of problems/bugs when
>> transactions and other specific features linked to connections (like
>> temporary tables) are involved (for example because a transaction is
>> always
>> associated with a single connection and that other connections, including
>> anonymous connections, cannot be part of it).
>>
>> These "under the hood" features has been removed from the .NET framework
>> and
>> if I were you, I wouldn''t hope to much on seeing them in the next
>> release.
>> If you need two open connections, then all you have to do is to open two
>> connections; no mess, no fuss.
>


8870

3/30/2005 12:25:00 PM

0

excuse me if I continue to insist on this problem. Perhaps someone from
Microsoft can tell us the reasons why they allows only one active DataReader
per database connection.
The classes System.Data.Odbc.OdbcConnection etc are a wrapper around the
ODBC api.
1) the java JDBC-ODBC bridge is a similar wrapper, and it allows the desired
feature (I have tried it)
2) the Mono implementation of System.Data.Odbc does also allow it (I have
just tried it)
3) for the MS .NET framework, it is possible only with one DB: SQL Server
2005. Why this?
It is clear that limitations in the ODBC api cannot be the reason for this
constraint, as it works with 1) and 2).

I would like to repeat how important this feature is. A typical
Client-Server application is made of dozens of database tables. A particular
task normally uses data from several tables. In general it is not possible to
access them all with one big query. With the limitation in the
System.Data.Odbc and System.Data.OleDB classes, all the data from the
preceding queries must be stored in the RAM of the Client before the next
query can be executed.
There are many reasons why that is a bad solution, here are a few examples:
-a query may return large amounts of data that fills the RAM
-often only the first ... records of the result are needed (based on an
abort condition determined by the code that consumes the records)
-often it would be nice to get at the first records of a query before the
last record has gone from the DB server to the client (for example to display
the first page(s) of a long report in the print preview while the rest of the
report is still being built in the background, or to display the first page
of data in a grid and read more records when the user scrolls down)
....


Sylvain Lafontaine

3/30/2005 3:59:00 PM

0

All you have to do is to open a second connection (this is how ODBC is doing
it) or to redesign your queries to retrieve only the needed results. You
can even make some of this work directly on the SQL-Server.

However, this will work with SQL 2005 because MS has added this capability
to ADO.NET 2.0 but I don''t know how they have implemented it so I cannot
tell you the real consequences of using this feature with SQL-Server
2005/ADO.NET 2.0.

Finally, the exemples you gave me have the default of imposing a big burden
on the resources of any SQL-Server. This is why such things as connected
and cached recordsets have been dropped from ADO.NET because it is nearly
impossible to scale them up on a high availability SQL-Server (which doesn''t
mean that they don''t work well when you are the only single person using
it). Good design practice require that you design your application in such
a way to have the less possibly burden on a partaged resource like a
SQL-Server. This is incompatible with a brut force technique.

S. L.

"8870" <8870@discussions.microsoft.com> wrote in message
news:3B1AE711-9EA4-4343-A096-F3627752F667@microsoft.com...
> excuse me if I continue to insist on this problem. Perhaps someone from
> Microsoft can tell us the reasons why they allows only one active
> DataReader
> per database connection.
> The classes System.Data.Odbc.OdbcConnection etc are a wrapper around the
> ODBC api.
> 1) the java JDBC-ODBC bridge is a similar wrapper, and it allows the
> desired
> feature (I have tried it)
> 2) the Mono implementation of System.Data.Odbc does also allow it (I have
> just tried it)
> 3) for the MS .NET framework, it is possible only with one DB: SQL Server
> 2005. Why this?
> It is clear that limitations in the ODBC api cannot be the reason for this
> constraint, as it works with 1) and 2).
>
> I would like to repeat how important this feature is. A typical
> Client-Server application is made of dozens of database tables. A
> particular
> task normally uses data from several tables. In general it is not possible
> to
> access them all with one big query. With the limitation in the
> System.Data.Odbc and System.Data.OleDB classes, all the data from the
> preceding queries must be stored in the RAM of the Client before the next
> query can be executed.
> There are many reasons why that is a bad solution, here are a few
> examples:
> -a query may return large amounts of data that fills the RAM
> -often only the first ... records of the result are needed (based on an
> abort condition determined by the code that consumes the records)
> -often it would be nice to get at the first records of a query before the
> last record has gone from the DB server to the client (for example to
> display
> the first page(s) of a long report in the print preview while the rest of
> the
> report is still being built in the background, or to display the first
> page
> of data in a grid and read more records when the user scrolls down)
> ...
>
>


8870

3/31/2005 10:05:00 AM

0

>All you have to do is to open a second connection
yes that is the only choice (the most costly in terms of resources)

>(this is how ODBC is doing it)
ODBC doesn''t in general open more connections in order to have more active
result sets. In my case (informix) there was only one connection and
therefore one transaction. (Maybe an ODBC driver for some particular DB does
really open more connections)

>or to redesign your queries to retrieve only the needed results.
I didn''t intend to read data that is not needed.

>You can even make some of this work directly on the SQL-Server.
probably you mean stored procedures.

>However, this will work with SQL 2005 because MS has added this capability
>to ADO.NET 2.0 but I don''t know how they have implemented it so I cannot
>tell you the real consequences of using this feature with SQL-Server
>2005/ADO.NET 2.0.

>Finally, the exemples you gave me have the default of imposing a big burden
>on the resources of any SQL-Server. This is why such things as connected
>and cached recordsets have been dropped from ADO.NET because it is nearly
>impossible to scale them up on a high availability SQL-Server (which doesn''t
>mean that they don''t work well when you are the only single person using
>it). Good design practice require that you design your application in such
>a way to have the less possibly burden on a partaged resource like a
>SQL-Server. This is incompatible with a brut force technique.
It is clear that open cursors need RAM on the DB server. Connected
recordsets may not be the optimal thing for every task, but they are very
useful in many situations and have worked well for years.
What is a brute force technique? Assume you have a table with 50000 records
and want to display/edit data from this table in a grid, and before you see
any record, all the 50000 must be downloaded into the DataSet of the client.
This is a waste of resources (network traffic, disk access, time). One could
say in the case of such large tables there should be a filter which limits
the records retrieved to 200, for example. But I think many users won''t
always specify an optimal filter. They open the window and want to see the
data. The software should be smart enough to do it in an efficient way.
Immagine you enter some criteria in an internet search engine, and it finds a
huge number of results, and before you see the first page all the results
must be downloaded to your client.
I think connected recordsets should be available when they are needed. If
they are useless, why did Microsoft introduce MARS in .NET 2.0 (but only for
their own SQL server)? I know no other DB client product that doesn''t support
this technique. In my opinion the change to be made in the System.Data.Odbc
classes would be minimal.