I am working on a project centered around an Oracle database (though honestly I don't expect that to matter) and I find myself have a fair amount of duplicate code, specifically exceptions. The best way I've seen so far is from this question https://stackoverflow.com/a/1554/865868, which suggests the use of delegates. This looked like the perfect solution until I tried to implement it in my project. I found that I had one case where it was not practical.
Let me describe my program a bit. I have two sections of code that deal with database operations. The idea is that I call a function that returns a DataTable, called LoadDataTable(). I then have a function that deals inserting items from a list into a table.
private void AddToList(List<string> itemList) {
try {
using (OracleConnection connection = new OracleConnection(connectionString)) {
connection.Open();
foreach (string item in itemList) {
using (OracleCommand command = new OracleCommand()) {
command.Connection = connection;
//Insert operation here
//......
command.ExecuteNonQuery();
}
}
} catch (OracleException ex) {
string messageboxtitle = "Database Exception";
switch (ex.Number) {
case 00001:
MessageBox.Show("Constraint Violation Error", messageboxtitle, MessageBoxButtons.OK);
break;
case 12154:
MessageBox.Show(string.Format("Connection Error: {0}", ex.Message), messageboxtitle);
break;
default:
MessageBox.Show(ex.ToString());
break;
}
}
}
private DataTable LoadDataTable() {
DataTable dataTable = new DataTable();
try {
using (OracleConnection connection = new OracleConnection(connectionString)) {
connection.Open();
using (OracleCommand command = new OracleCommand()) {
command.Connection = connection;
command.CommandText = sql;
command.CommandType = CommandType.Text;
using (OracleDataAdapter oda = new OracleDataAdapter(command)) {
oda.Fill(dataTable);
}
}
}
} catch (OracleException ex) {
string messageboxtitle = "Database Exception";
switch (ex.Number) {
case 12154:
MessageBox.Show(string.Format("Connection Error: {0}", ex.Message), messageboxtitle); //Duplicate Exception
break;
default:
MessageBox.Show(ex.ToString());
break;
}
}
return dataTable;
}
Keep in mind I had to rewrite and simplify that code so I could discuss it. Anyway, looking at the delegate example I quickly realized that paramaters are an issue. You can't use params for List<string>
types, but there is no doubt in the usefulness of the delegates as I would be able to one one centralized section for exceptions that are not duplicated.
private delegate void DatabaseOperation(List<string> itemList);
private void PerformDatabaseOperation(DatabaseOperation operation, List<string> itemList){
try {
operation(itemList);
} catch (OracleException ex) {
string messageboxtitle = "Database Exception";
switch (ex.Number) {
case 00001:
MessageBox.Show("Constraint Violation Error", messageboxtitle, MessageBoxButtons.OK);
break;
case 12154:
MessageBox.Show(string.Format("Connection Error: {0}", ex.Message), messageboxtitle);
break;
default:
MessageBox.Show(ex.ToString());
break;
}
}
}
private void AddToList(List<string> itemList) {
using (OracleConnection connection = new OracleConnection(connectionString)) {
connection.Open();
foreach (string item in itemList) {
using (OracleCommand command = new OracleCommand()) {
command.Connection = connection;
//Insert operation here
//......
command.ExecuteNonQuery();
}
}
}
How to use:
List<string> itemList = new List<string>();
//code to fill list
PerformDatabaseOperation(AddToList, itemList);
Problem is now that I am unable to implement LoadDataTable() with this delegate as it does not have any parameters. The use of params
on the delegate does not work since List is incompatible. I'm looking to improve my coding techniques for re usability and readability but I find myself spinning my wheels reading various threads on the subject, mostly since they do not go in depth enough beyond a simple example that doesn't really catch the problem I find myself having now. To ensure this gets answered let me pose a final question. How could I write code which would avoid duplicating exceptions?
UPDATE
For anyone looking to solve a similar problem, see below. Keep in my there is plenty more that can be done to improve the code. Also, anyone interested in the discussion around the var
keyword discussed here, go here. I hope this helps:
private delegate void DatabaseOperation();
private void PerformDatabaseOperation(DatabaseOperation operation) {
try {
operation();
} catch (OracleException ex) {
string messageboxtitle = "Database Exception";
switch (ex.Number) {
case 00001:
MessageBox.Show("Constraint Violation Error", messageboxtitle, MessageBoxButtons.OK);
break;
case 12154:
MessageBox.Show(string.Format("Connection Error: {0}", ex.Message), messageboxtitle);
break;
default:
MessageBox.Show(ex.ToString());
break;
}
}
}
private void AddToList(List<string> itemList) {
using (OracleConnection connection = new OracleConnection(connectionString)) {
connection.Open();
foreach (string item in itemList) {
using (OracleCommand command = new OracleCommand()) {
command.Connection = connection;
//Insert operation here
//......
command.ExecuteNonQuery();
}
}
}
private DataTable LoadDataTable() {
DataTable dataTable = new DataTable();
using (OracleConnection connection = new OracleConnection(connectionString)) {
connection.Open();
using (OracleCommand command = new OracleCommand()) {
command.Connection = connection;
command.CommandText = sql;
command.CommandType = CommandType.Text;
using (OracleDataAdapter oda = new OracleDataAdapter(command)) {
oda.Fill(dataTable);
}
}
}
return dataTable;
}
>` instead.
– Federico Berasategui May 13 '13 at 19:58