The IDataReader is an Interface. This means that it only contains a signature of the class structure. Every class which implements this interface need to implement the same methods.
In this way you can call any class and be sure that they all support the same functionality.
as MSDN states in the IDataReader, this interfaceprovides a means of reading one or more forward-only streams of result sets obtained by executing a command at a data source, and is implemented by .NET Framework data providers that access relational databases.If you search for the members of the IDataReader, you will see that properties like e.g. IsClosed and RecordsAffected and also methods like e.g. Close, NextResult and Read should be implemented when a class derives from from the IDataReader interface.
The DBDataReader is a class which implements this interface. According to msdnreads a forward-only stream of rows from a data source.If you look at the signature of the DbDataReader class,
public abstract class DbDataReader : MarshalByRefObject, IDataReader,
IDisposable, IDataRecord, IEnumerable
But there is more. The DbDataReader class is a abstract class, which means that you can not create an object of this class (can not be instantiated). This is only intended to use as a base class for other classes. But is does implement already some functionality. Something which can not be done in an interface.
You can find on msdn the derived classes of the DbDataReader Class. You will find there the e.g. SqlDataReader class.
The SqlDataReader class inherits from the DbDataClass and adds some (Microsoft) SQL-server specific code. So, the SqlDataReader is a class which provides a way of reading a forward-only stream of rows from a (Microsoft) SQLServer database.
When to use: it depends on the situation, but most of the time you will use the SqlDataReader Class.
If you write your own dataobject you can interit from the abstract DbDataReader class. Or if you want to implement all code yourself and only need the functionanlity of the IDataReader interface, you use this one.
It is ofcourse possible to cast an object back to the interface if you don't know the exact type, but you do know that the interface is implemented. But that would take us a bit to far at this very moment.