get() 请求中 SQL 语句/连接的最佳实践

本文关键字:连接 最佳 语句 请求 SQL get | 更新日期: 2023-09-27 18:31:54

对于简单的查找,我需要在 DB2 机器上执行一些 SQL 语句。 我目前无法使用ORM。 我通过这段代码有一个工作示例,但是我想知道是否可以对其进行更多优化,因为这基本上会在每个请求上创建一个连接。 这似乎只是糟糕的编程。

有没有办法优化这个 Get() 请求以保持连接打开状态? 嵌套using语句似乎也很脏。 我应该如何处理Get()无论如何都真的想返回用户对象的事实;甚至错误? 我可以将此连接放在程序的开头,以便我可以一遍又一遍地使用它吗? 对此有哪些最佳实践?

public class UsersController : ApiController
{
    String constr = WebConfigurationManager.ConnectionStrings["DB2Connection"].ConnectionString;
    public User Get([FromUri] User cst)
    {
        if (cst == null)
        {
            throw new HttpResponseException(HttpStatusCode.NotFound);
        }
        else
        {
            using (OdbcConnection DB2Conn = new OdbcConnection(constr))
            {
                DB2Conn.Open();
                using (OdbcCommand com = new OdbcCommand(
                    // Generic SQL Statement
                    "SELECT * FROM [TABLE] WHERE customerNumber = ?", DB2Conn))
                {
                    com.Parameters.AddWithValue("@var", cst.customerNumber);
                    using (OdbcDataReader reader = com.ExecuteReader())
                    {
                        try
                        {
                            while (reader.Read())
                            {
                                cst.name = (string)reader["name"];
                                return cst;
                            }
                        }
                        catch
                        {
                            throw;
                        }
                    }
                }
            }
            return cst;
        }
    }
}

我发现了一个没有详细答案的好问题,我觉得这两个问题都有类似的解决方案......

get() 请求中 SQL 语句/连接的最佳实践

这似乎只是糟糕的编程。

你为什么这么认为?

基础系统应为您维护连接池中的连接。 创建连接应该已经非常优化了。

从逻辑的角度来看,你现在正在做的事情正是你想做的。 创建连接,使用它,并立即释放它。 这允许其他线程/进程/等从连接池使用它,现在您已经完成了它。

这也避免了在使用它们的代码之外手动维护打开的连接而产生的无数问题。

有没有办法优化这个 Get() 请求以保持连接打开状态?

您是否测量过实际的性能问题? 如果没有,就没有什么可以优化的。

而且,在

Web 应用程序的静态上下文中挂起打开的连接很有可能会对性能产生重大影响。

<小时 />

总之。。。您已经正确执行此操作。 (好吧,除了不必要的尝试/捕获。 您可以删除它。

<小时 />

编辑:如果您只是想提高代码的可读性(这本身就是个人喜好的问题),这对我来说似乎是可读的:

public User Get([FromUri] User cst)
{
    if (cst == null)
        throw new HttpResponseException(HttpStatusCode.NotFound);
    using (var DB2Conn = new OdbcConnection(constr))
    using (var com = new OdbcCommand("SELECT * FROM [TABLE] WHERE customerNumber = ?", DB2Conn))
    {
        com.Parameters.AddWithValue("@var", cst.customerNumber);
        DB2Conn.Open();
        using (OdbcDataReader reader = com.ExecuteReader())
            while (reader.Read())
            {
                cst.name = (string)reader["name"]
                return cst;
            }
    }
    return cst;
}

请注意,您可以通过重新寻址该 SQL 查询的逻辑来进一步改进它。 由于您是从一条记录中获取一个值,因此您无需遍历数据读取器。 只需获取单个文字并返回即可。 请注意,这是徒手且未经测试的,但它可能看起来像这样:

public User Get([FromUri] User cst)
{
    if (cst == null)
        throw new HttpResponseException(HttpStatusCode.NotFound);
    using (var DB2Conn = new OdbcConnection(constr))
    using (var com = new OdbcCommand("SELECT name FROM [TABLE] WHERE customerNumber = ? FETCH FIRST 1 ROWS ONLY", DB2Conn))
    {
        com.Parameters.AddWithValue("@var", cst.customerNumber);
        DB2Conn.Open();
        cst.name = (string)com.ExecuteScalar();
    }
    return cst;
}

>@David的答案完美地解决了你的实际问题,但这里有一些其他观察结果,可能会让你的代码更容易接受:

  • 删除 try/catch 块 - 您所做的只是重新抛出异常,如果您根本不使用 try/catch 就会发生这种情况。 除非你能做些什么,否则不要抓住异常。 (我现在看到@David的答案解决了 - 要么它是在我阅读后添加的,要么我错过了它 - 我对重叠表示歉意,但值得加强)
  • 将查询更改为仅拉取name并使用ExecuteScalar而不是ExecuteReader。 您正在从第一条记录中获取name值并退出while循环。 ExecuteScalar返回第一条记录中第一列的值,因此您可以消除while循环及其using