私は Oracle データベースを中心としたプロジェクトに取り組んでおり (正直なところ、それが問題になるとは思いませんが)、かなりの量の重複コード、特に例外があることに気付きました。これまでに見た最良の方法は、デリゲートの使用を示唆するこの質問https://stackoverflow.com/a/1554/865868からのものです。プロジェクトに実装しようとするまで、これは完璧なソリューションのように見えました。実用的でないケースが 1 つあることがわかりました。
私のプログラムを少し説明させてください。データベース操作を扱う 2 つのコード セクションがあります。アイデアは、LoadDataTable() と呼ばれる DataTable を返す関数を呼び出すことです。次に、リストからテーブルへのアイテムの挿入を処理する関数があります。
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;
}
議論できるように、そのコードを書き直して単純化する必要があったことを覚えておいてください。とにかく、デリゲートの例を見ると、パラメーターが問題であることがすぐにわかりました。型にparams を使用することはできませんList<string>
が、重複していない例外に対して 1 つの集中化されたセクションを作成できるため、デリゲートの有用性に疑いの余地はありません。
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();
}
}
}
使い方:
List<string> itemList = new List<string>();
//code to fill list
PerformDatabaseOperation(AddToList, itemList);
問題は、パラメーターがないため、このデリゲートで LoadDataTable() を実装できないことです。params
List は互換性がないため、デリゲートでの の使用は機能しません。再利用性と可読性のためにコーディング手法を改善しようとしていますが、問題を実際にキャッチしない単純な例を超えて十分に深く進んでいないため、主に主題に関するさまざまなスレッドを読んで車輪を回転させていることに気付きます。自分が今持っていることに気づきます。これが確実に解決されるようにするために、最後の質問をさせてください。例外の重複を回避するコードを作成するにはどうすればよいですか?
アップデート
同様の問題を解決しようとしている人は、以下を参照してください。コードを改善するためにできることは他にもたくさんあります。var
また、ここで議論されているキーワードに関する議論に興味がある人は、ここにアクセスしてください。これが役立つことを願っています:
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;
}