For abstract classes try to think of the most common members of multiple classes that are all similar. An example of this is DbConnections:
Oracle, SQL, OleDb, and ODBC connections...
public sealed class SqlConnection : DbConnection, ICloneable
public sealed class OleDbConnection : DbConnection, ICloneable, IDbConnection, IDisposable
public sealed class OdbcConnection : DbConnection, ICloneable
public sealed class OracleConnection : DbConnection, ICloneable
All descend from the abstract base...
public abstract class DbConnection : Component, IDbConnection, IDisposable
Connection specific properties such as DSN can be added as members to the ODBC class since it only applies to that individual connection (but in this case the DSN is the connection string). Now that we have abstracted the major connection types to a common class, we can use DbCommand.Execute() to handle any type of DB connection from the same code.
The difference in descending versus an abstract class is that you can not instantiate an abstract class, a class must be derived from it in order for it to be usable. A database connection by itself is a concept, an abstract concept. A connection to MSSQL-Server is an implementation of the concept which can be instantiated.
I have a database connection wrapper class I use for my data access, here is an example:
private DbConnection GetDbConnection()
DbConnection result = null;
result = new OdbcConnection(_connectionString);
result = new OleDbConnection(_connectionString);
result = new OracleConnection(_connectionString);
result = new SqlConnection(_connectionString);
throw new InvalidEnumArgumentException("Invalid enumeration member", (int)_connectionType, _connectionType.GetType());
public int Execute(string query, List<DataParameter> parms)
int result = 0;
using (DbConnection conn = GetDbConnection())
using (DbCommand cmd = GetDbCommand(query, parms, conn))
result = cmd.ExecuteNonQuery();