all groups > dotnet ado.net > january 2007 >
You're in the

dotnet ado.net

group:

Custom ADO.NET Provider, question about DbCommand.ExecuteReader


Re: Custom ADO.NET Provider, question about DbCommand.ExecuteReader Robert Simpson
1/30/2007 8:03:00 AM
dotnet ado.net:
[quoted text, click to view]

The default DbCommand.ExecuteReader() functions call the protected
ExecuteDbDataReader() function, which is what you'll be implementing in your
derived class.

If you want to be complete however, you should use the "new" keyword and
override the two ExecuteReader() functions as well so they return your
type-specific data reader. For example, here's my implementation of those 3
functions:

protected override DbDataReader ExecuteDbDataReader(CommandBehavior
behavior)
{
return ExecuteReader(behavior);
}

public new SQLiteDataReader ExecuteReader()
{
return ExecuteReader(CommandBehavior.Default);
}


public new SQLiteDataReader ExecuteReader(CommandBehavior behavior)
{
InitializeForReader();

SQLiteDataReader rd = new SQLiteDataReader(this, behavior);
_activeReader = rd;

return rd;
}

Custom ADO.NET Provider, question about DbCommand.ExecuteReader Jed Ozone
1/30/2007 9:54:14 AM
I'm converting over a ADO.NET provider I wrote in 1.1 .NET to 2.0. I don't
understand why the DbCommand.ExecuteReader methods (it's overloaded) is not
virtual or abstract. This method would most likely need to be modified by
any class inheriting DbCommand. On the other hand, DbCommand.ExecuteScaler
is abstract, which is exactly what I would thought DbCommand.ExecuteReader
methods should be.

What would the default implemenation of DbCommand.ExecuteReader() actually
do? Just pass back a DbDataReader object?

If I use the "new" keyword to replace the ExecuteReader methods, I'm scared
polymorphsim will be broken (and some of the factory stuff and other generic
coding won't work).


Re: Custom ADO.NET Provider, question about DbCommand.ExecuteReader Jed Ozone
1/30/2007 10:25:02 AM
Ah, that makes perfect sense. I couldn't find any documentation on this on
MDSN, but your explanation was perfect. Much thanks!

[quoted text, click to view]

Re: Custom ADO.NET Provider, question about DbCommand.ExecuteReader David Browne
1/30/2007 11:24:12 AM


[quoted text, click to view]

Why would you want to do that? Then you'll run different code depending on
the type the client binds to. You definitely wouldn't want different
behavior in these cases, so why hide the method?

[quoted text, click to view]

??????

David
Re: Custom ADO.NET Provider, question about DbCommand.ExecuteReader Robert Simpson
1/30/2007 12:24:57 PM
"David Browne" <davidbaxterbrowne no potted meat@hotmail.com> wrote in
message news:u$cy2NJRHHA.3316@TK2MSFTNGP02.phx.gbl...
[quoted text, click to view]

No you won't. Please explain how the behaviors are different ...

Scenario 1: User calls DbCommand.ExecuteReader(...)
Result: The base DbCommand function calls the overridden
ExecuteDbDataReader() which in turn calls my "new" ExecuteReader() and
returns a type-specific SQLiteDataReader.

Scenario 2: User calls SQLiteCommand.ExecuteReader(...)
Result: The "new" ExecuteReader function returns a type-specific
SQLiteDataReader.

Both scenarios drill down to my "new" implementation of ExecuteReader()
which returns a type-specific DataReader for my object. Scenario 1 has 1
extra function call, and the base DbCommand function casts the resulting
object down to a DbDataReader, but that's what its supposed to do anyway.

[quoted text, click to view]

Perhaps you should break out Lutz's Reflector and have a gander at
SqlClient.SqlCommand and see how they do it ... you'll find my method
remarkably similar to Microsoft's approach.

Robert

Re: Custom ADO.NET Provider, question about DbCommand.ExecuteReader David Browne
1/30/2007 3:36:43 PM


[quoted text, click to view]

The two aren't different, if you code them to do the exact same thing. But
why would you want to hide a method with an implementation that does the
exact same thing as the overriden method?

How do you know that DbCommand.ExecuteReader doesn't do anything other than
call the protected method? What if this changes in the future?

[quoted text, click to view]

So you have two different code paths to maintain that both do exactly the
same thing.

David
Re: Custom ADO.NET Provider, question about DbCommand.ExecuteReader Robert Simpson
1/30/2007 3:40:21 PM
"David Browne" <davidbaxterbrowne no potted meat@hotmail.com> wrote in =
message news:ufyK9aLRHHA.4632@TK2MSFTNGP04.phx.gbl...
[quoted text, click to view]

The point is, they do not do the same thing. One returns a =
DbDataReader, and the other returns a SQLiteDataReader. While you can =
implicitly cast a SQLiteDataReader to a DbDataReader, you cannot =
implicitly cast in the other direction and hence the different codepaths =
are distinct in purpose.

[quoted text, click to view]

It cannot and will not change. DbCommand.ExecuteReader() has no =
knowledge of implementation, and leaves implementation up to the =
provider via the ExecuteDbDataReader(). Its behavior is documented and =
will not change. If in the future Microsoft determines that additional =
functionality is needed, they will create a new function for it and will =
not break the millions of deployed apps already out in the wild.
=20
[quoted text, click to view]

There is one code path, and they do not do the same thing. All paths =
converge at the new type-specific ExecuteReader(CommandBehavior) =
function. There is no duplication of anything.

Lets start by examining two sample usages, one with the built-in =
Microsoft Sql Server provider, and the other with mine:

// SqlClient version
using (SQCommand cmd =3D sqlcnn.CreateCommand())
{
cmd.CommandText =3D "SELECT GetDate()";
using(SqlDataReader reader =3D cmd.ExecuteReader())
{
// etc etc
}
}

// SQLite version
using (SQLiteCommand cmd =3D sqlitecnn.CreateCommand())
{
cmd.CommandText =3D "SELECT * FROM sqlite_master";
using(SQLiteDataReader reader =3D cmd.ExecuteReader())
{
// etc etc
}
}

The above code samples are nearly identical, and are common usage =
scenarios that happen frequently. If I were to remove the "new" =
ExecuteReader functions in my implementation of SQLiteCommand, then the =
above code would no longer compile against my provider. The reason it =
would no longer compile is because there would be no version of =
ExecuteReader() that returns a SQLiteDataReader and the call to =
cmd.ExecuteReader() would require an explicit up-cast.

Leaving out the "new" ExecuteReader() functions would be inconsistent =
with the way the other ADO.NET providers behave. The rule seems to be, =
"be specific when being specific, and be generic when being generic."

In either case, the code below will compile in any circumstance, but =
using the "be generic when being generic" rule:

using (DbCommand cmd =3D sqlitecnn.CreateCommand())
{
cmd.CommandText =3D "SELECT * FROM sqlite_master";
using (DbDataReader reader =3D cmd.ExecuteReader())
{
// etc etc
}
}

If you'd like more examples, look at the following:

SqlConnection.CreateCommand() vs. DbConnection.CreateCommand()
SqlCommand.CreateParameter() vs. DbCommand.CreateParameter()

In each of these cases as well, the SqlConnection and SqlCommand objects =
have overridden using "new" the CreateXXX() functions in addition to =
overriding the virtual base implementations (CreateDbParameter and =
CreateDbCommand) so as to return a generic or type-specific object =
without forcing the user to explicitly upcast.

It's merely a matter of convenience to the user so they can be as =
specific or as generic as they like without forcing them to explicitly =
cast the return values.

Re: Custom ADO.NET Provider, question about DbCommand.ExecuteReader Robert Simpson
1/30/2007 3:46:25 PM
Bah ... typo in that SqlClient example ...

// SqlClient version
using (SqlCommand cmd = sqlcnn.CreateCommand())
{
cmd.CommandText = "SELECT GetDate()";
using(SqlDataReader reader = cmd.ExecuteReader())
{
// etc etc
}
}

AddThis Social Bookmark Button