1

私は 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() を実装できないことです。paramsList は互換性がないため、デリゲートでの の使用は機能しません。再利用性と可読性のためにコーディング手法を改善しようとしていますが、問題を実際にキャッチしない単純な例を超えて十分に深く進んでいないため、主に主題に関するさまざまなスレッドを読んで車輪を回転させていることに気付きます。自分が今持っていることに気づきます。これが確実に解決されるようにするために、最後の質問をさせてください。例外の重複を回避するコードを作成するにはどうすればよいですか?

アップデート

同様の問題を解決しようとしている人は、以下を参照してください。コードを改善するためにできることは他にもたくさんあります。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;
}
4

3 に答える 3

2

Oracle をサポートしているPetaPocoなどのマイクロ ORM を使用することをお勧めします。自動生成できるのに、なぜそのようなコードをすべて書くのでしょうか? 独自のデータ アクセス レイヤーを作成する場合は、次のようなクラスの CRUD メソッドを作成することをお勧めします。

 public bool Insert(Person p)
 {...} 

次のような一般的な方法を使用してこれを行うことも検討できます。

public bool Insert<T>(T item)
{...} 
于 2013-05-13T20:10:44.133 に答える
-1

さまざまなパラメーターを渡すためによく使用されるパターンの 1 つは、パラメーターをコンストラクターに渡すことです。利点は、コンストラクターがインターフェイスの一部ではないことです。ただし、デリゲートではなくオブジェクトを操作する必要があります。

public interface IDatabaseOperation
{
    void Execute();
}

public class LoadListDatabaseOperation : IDatabaseOperation
{
    private List<string> _itemList;

    public LoadListDatabaseOperation(List<string> itemList)
    {
        _itemList = itemList;
    }

    public void Execute()
    {
        ...
        // Fill the list here
        ...
    }
}

オブジェクトを渡すのは少しコストがかかりますが、さまざまな専門化度を持つ操作の階層を作成できるなどの利点もあります。一般的な基本操作と、特定の型に特化した派生操作がある場合があります。スカラー戻り値などのプロパティを使用することもできます。

于 2013-05-13T20:01:26.087 に答える