The Problem
I have some code which I've coded in such a way to enable high maintainability and code re-usability. I am concerned about a particular piece of code and I would like a professional opinion on if this code will crumble under high stress.
The Codez ##
public abstract class PlexxisDataTransferObjects : PlexxisDatabaseRow
{
//static methods
public static List<PlexxisDatabaseRow> GetAll();
//Constructors
public PlexxisDataTransferObjects(){ }
//Methods
public abstract bool Insert(OracleConnection Conn);
public abstract bool Update(OracleConnection Conn);
public abstract bool Delete(OracleConnection Conn);
public bool Insert()
{
using (var Conn = new OracleConnection(ConnectionString))
{
Conn.Open();
return Insert(Conn);
}
}
public bool Update()
{
using (var Conn = new OracleConnection(ConnectionString))
{
Conn.Open();
return Update(Conn);
}
}
public bool Delete()
{
using (var Conn = new OracleConnection(ConnectionString))
{
Conn.Open();
return Delete(Conn);
}
}
}
//Data Transfer Objects
public sealed class Apps : PlexxisDataTransferObjects
{
//Static Methods
public override static List<PlexxisDatabaseRow> GetAll()
{
List<PlexxisDatabaseRow> collection = new List<PlexxisDatabaseRow>();
using (var Conn = new OracleConnection(ConnectionString))
{
using (var Command = new OracleCommand("select * from APPS", Conn))
{
Conn.Open();
using (var reader = Command.ExecuteReader(CommandBehavior.CloseConnection))
while (reader.Read())
collection.Add(new Apps(reader));
}
}
return collection;
}
//Fields
public int AppId;
public string AuthKey;
public string Title;
public string Description;
public bool isClientCustomApp;
//Constructors
public Apps() : base () { }
public Apps(OracleDataReader reader) : base ()
{
if (reader["APP_ID"] != DBNull.Value)
this.AppId = Convert.ToInt32(reader["APP_ID"]);
if (reader["AUTH_KEY"] != DBNull.Value)
this.AuthKey = Convert.ToString(reader["AUTH_KEY"]);
if (reader["TITLE"] != DBNull.Value)
this.Title = Convert.ToString(reader["TITLE"]);
if (reader["DESCRIPTION"] != DBNull.Value)
this.Description = Convert.ToString(reader["DESCRIPTION"]);
if (reader["IS_CLIENT_CUSTOM_APP"] != DBNull.Value)
this.isClientCustomApp = Convert.ToBoolean(reader["IS_CLIENT_CUSTOM_APP"]);
}
//Methods
public override bool Insert(OracleConnection Conn)
{
string sql = string.Empty;
sql += "INSERT INTO APPS (APP_ID, AUTH_KEY, TITLE, DESCRIPTION, IS_CLIENT_CUSTOM_APP)";
sql += "VALUES(:appid, :authkey, :title, :description, :iscust)";
using (var Command = new OracleCommand(sql, Conn))
{
AppId = GetId();
Command.Parameters.Add(":appid", OracleDbType.Int32).Value = AppId;
Command.Parameters.Add(":authkey", OracleDbType.Varchar2).Value = AuthKey;
Command.Parameters.Add(":title", OracleDbType.Varchar2).Value = Title;
Command.Parameters.Add(":description", OracleDbType.Varchar2).Value = Description;
Command.Parameters.Add(":iscust", OracleDbType.Int32).Value = Convert.ToInt32(isClientCustomApp);
return Convert.ToBoolean(Command.ExecuteNonQuery());
}
}
public override bool Update(OracleConnection Conn)
{
string sql = string.Empty;
sql += "UPDATE APPS SET ";
sql += "AUTH_KEY = :authkey, TITLE = :title, DESCRIPTION = :description, IS_CLIENT_CUSTOM_APP = :iscust ";
sql += "WHERE APP_ID = :appid";
using (var Command = new OracleCommand(sql, Conn))
{
Command.Parameters.Add(":authkey", OracleDbType.Varchar2).Value = AuthKey;
Command.Parameters.Add(":title", OracleDbType.Varchar2).Value = Title;
Command.Parameters.Add(":description", OracleDbType.Varchar2).Value = Description;
Command.Parameters.Add(":iscust", OracleDbType.Int32).Value = Convert.ToInt32(isClientCustomApp);
Command.Parameters.Add(":appid", OracleDbType.Int32).Value = AppId;
return Convert.ToBoolean(Command.ExecuteNonQuery());
}
}
public override bool Delete(OracleConnection Conn)
{
string sql = string.Empty;
sql += "DELETE FROM APPS ";
sql += "WHERE APP_ID = :appid";
using (var Command = new OracleCommand(sql, Conn))
{
Command.Parameters.Add(":appid", OracleDbType.Int32).Value = AppId;
return Convert.ToBoolean(Command.ExecuteNonQuery());
}
}
}
What Am I looking at?
What concerns me the most is the Insert, Update and Delete method in the abstract class calling the Insert, Update and Delete in the concrete class.
I've done it this way so that I could enable transactions if necessary by opening a connection and explicitly starting a transaction, send the transaction and still have the objects do what they need to do; furthermore, if I had to explicitly rewrite the 3 methods for 40 or so classes, it could become quite cumbersome.
However, I'm concerned that by opening the connection early that I might be holding up the database. I don't know how much input data that might be being updated at any given time. In this situation I have two major thoughts, I can either make the insert, update and delete abstract in the abstract class and implement them while explicitly opening the connection immediately before the Command.ExecuteNonQuery() or I can leave it how it is now.
What would I like from you?
First and foremost, your opinion on the situation. Secondly pointing out any pitfalls behind the logic or any bad coding that you happen to spot would also be very helpful.