C# 与数据库代码简化

标签 c# database performance

我正在从事一个以 Oracle 数据库为中心的项目(老实说,我不认为这有什么关系),我发现自己有相当多的重复代码,特别是异常。到目前为止我看到的最好的方法是从这个问题https://stackoverflow.com/a/1554/865868 ,这建议使用委托(delegate)。这看起来像是完美的解决方案,直到我尝试在我的项目中实现它。我发现我有一个案例是不实用的。

让我稍微描述一下我的程序。我有两段代码处理数据库操作。我的想法是调用一个返回数据表的函数,称为 LoadDataTable()。然后我有一个函数可以将列表中的项目插入到表中。

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;
}

请记住,我必须重写和简化该代码,以便我可以讨论它。无论如何,看着委托(delegate)示例,我很快意识到参数是一个问题。您不能将参数用于 List<string>类型,但毫无疑问,代表的用处是因为我可以将一个集中的部分用于不重复的异常。

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);

现在的问题是我无法使用此委托(delegate)实现 LoadDataTable(),因为它没有任何参数。 params的使用由于 List 不兼容,对委托(delegate)不起作用。我正在寻求改进我的编码技术以提高可重用性和可读性,但我发现自己在阅读有关该主题的各种线索时手忙脚乱,主要是因为它们没有深入到一个简单的例子之外,而这个例子并没有真正捕获我的问题发现自己现在。为了确保这个问题得到回答,让我提出最后一个问题。我怎样才能编写避免重复异常的代码?

更新

对于希望解决类似问题的任何人,请参阅下文。记住我还有很多可以改进代码的地方。此外,任何对围绕 var 的讨论感兴趣的人此处讨论的关键字,go here .我希望这会有所帮助:

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;
}

最佳答案

请记住,委托(delegate)从父方法的主体中捕获变量。这也称为 closure .因此,委托(delegate)通常不需要有参数列表。

var itemList = new List<string>();
PerformDatabaseOperation(
    () => {
        ...
        itemList.Add(...);
        ...
    }
);

更新

你可以这样调用它:

List<string> itemList = new List<string>();
PerformDatabaseOperation(() => AddToList(itemList));

诀窍是将 lambda 表达式传递给没有参数的 PerformDatabaseOperation(空大括号 ()); PerformDatabaseOperation 也有没有 itemList 参数。 lambda 表达式的主体使用在调用 PerformDatabaseOperation 之前声明和初始化的 itemList。 C# 编译器魔术完成剩下的工作。

关于C# 与数据库代码简化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16529990/

相关文章:

Android WebView 导致 StrictMode 违规

performance - 如何将 ASGI 框架与 ASGI 服务器进行比较?

c# - ManagementObject 类未出现在 System.Management 命名空间中

c# - 是否有扫描执行某些操作的作业表的标准模式?

database - 绑定(bind)到一个数据库列的多个 UI 控件的聚合

java - 使用数据库进行登录验证

c++ - 从 'enable_shared_from_this' 派生一个类可以提高性能吗?

c# - 如何找到哪个 sql server 参数在 .net 中抛出异常?

c# - Windows 窗体应用程序 : help text on a grid view

sql - 如何在数据库中搜索特定字段