适合c#应用的参数化查询类- sql server

本文关键字:sql server 查询 应用 参数 适合 | 更新日期: 2023-09-27 17:49:38

我开始将我的查询封装在单个参数化查询类

现在你可以评估我的类的性能安全性和其他所有可能的方面吗?

你有什么建议吗

这里是select class

public static DataSet cmd_SelectQuery(string srCommandText, List<string> lstParameterNames, List<string> lstParameters)
{
    DataSet dsCmdPara = new DataSet();
    try
    {
        using (SqlConnection connection = new SqlConnection(DbConnection.srConnectionString))
        {
            using (SqlCommand cmd = new SqlCommand(srCommandText, connection))
            {
                cmd.CommandType = CommandType.Text;
                for (int i = 0; i < lstParameterNames.Count; i++)
                {
                    cmd.Parameters.AddWithValue(lstParameterNames[i], lstParameters[i]);
                }
                connection.Open();
                using (SqlDataAdapter sqlDa = new SqlDataAdapter(cmd))
                {
                    sqlDa.Fill(dsCmdPara);
                    return dsCmdPara;
                }
            }
        }
    }
    catch (Exception E)
    {
        csPublicFunctions.insertIntoTblSqlErrors(srCommandText + " " + E.Message.ToString());
    }
    return dsCmdPara;
}

这里是我的更新,删除类

public static void cmd_UpdateDeleteQuery(string srCommandText, List<string> lstParameterNames, List<string> lstParameters)
{
    try
    {
        using (SqlConnection connection = new SqlConnection(DbConnection.srConnectionString))
        {
            using (SqlCommand cmd = new SqlCommand(srCommandText, connection))
            {
                cmd.CommandType = CommandType.Text;
                for (int i = 0; i < lstParameterNames.Count; i++)
                {
                    cmd.Parameters.AddWithValue(lstParameterNames[i], lstParameters[i]);
                }
                connection.Open();
                cmd.ExecuteNonQuery();
            }
        }
    }
    catch (Exception E)
    {
        csPublicFunctions.insertIntoTblSqlErrors(srCommandText + " " + E.Message.ToString());
    }
}

谢谢你的回答

适合c#应用的参数化查询类- sql server

由于我是在手机上写这篇文章,所以有两个快速的建议。

  1. 接收对象,而不是字符串
  2. 将params object[]作为参数列表可能会使你的方法使用起来更自然。

代码是有效且正确的。你要求反馈,所以我有以下几点:

(1)在构建参数的代码中,最好指定数据类型。

for (int i = 0; i < lstParameterNames.Count; i++)
{
    var parameter = cmd.Parameters.AddWithValue(lstParameterNames[i], lstParameters[i]);
    parameter.SqlDbType = SqlDbType.NVarChar; // or whatever type you need
}

(2)你不需要显式地打开/关闭连接,因为Fill方法已经为你完成了。

connection.Open();
using (SqlDataAdapter sqlDa = new SqlDataAdapter(cmd))
{
    sqlDa.Fill(dsCmdPara);
    connection.Close();
    return dsCmdPara;
}

(3)如果你只打算有一个表,使用DataTable而不是DataSet。它会更快,更简单。

(4)这更像是一个风格点,但我发现显式关闭连接非常有帮助。如果结束语中有一个异常,有行号(通过pdb)是非常有用的。此外,它还有助于确保在忘记using时不会泄漏连接。


编辑

我想澄清第4点。假设当连接关闭时,清理导致了异常。如果不显式关闭连接,则会在Dispose方法中引发异常,该方法可能正在执行一堆其他工作。这使得很难看到做了什么导致了问题。

看这个简单的例子。有一个底层资源需要清理(Dispose的全部原因),它会抛出一个异常。

public class Resource: IDisposable
{
    public void Close()
    {
        CleanupMemory();
    }
    private void CleanupMemory()
    {
        throw new Exception();
    }
    public void Dispose()
    {
        CleanupMemory();
    }
}

两种不同方法的(清理后的)堆栈跟踪如下:

using (var r = new Resource())
{
    r.Close();
}
   at ConsoleApplication1.Resource.CleanupMemory() in Program.cs:line 31
   at ConsoleApplication1.Resource.Close() in Program.cs:line 26
   at ConsoleApplication1.Program.Main(String[] args) Program.cs:line 16

using (var r = new Resource())
{
}

   at ConsoleApplication1.Resource.CleanupMemory() in Program.cs:line 35
   at ConsoleApplication1.Resource.Dispose() in Program.cs:line 40
   at ConsoleApplication1.Program.Main(String[] args) in Program.cs:line 18

在第一个例子中,我知道我调用Close导致了异常,我有一个地方开始调试。如果只知道抛出了异常,则需要完全依赖异常中的信息。我没有其他的背景了。而且大多数异常消息都不是特别清楚。:)

都是完全正确的,只是不同而已。

埃里克

public DataTable Get_DTable(String Query, Dictionary<String, String> Parameters)
    {
        try
        {
            using (con = new SqlConnection(cls_Connection.URL()))
            {
                if (con.State == 0)
                    con.Open();
                using (cmd = new SqlCommand(Query, con))
                {
                    foreach (KeyValuePair<string, string> item in Parameters)
                    {
                        cmd.Parameters.AddWithValue(item.Key, item.Value);
                    }
                    using (da = new SqlDataAdapter(cmd))
                    {
                        using (dt = new DataTable())
                        {
                            da.Fill(dt);
                            if (dt.Rows.Count > 0)
                            {
                                return dt;
                            }
                        }
                    }
                }
            }
        }
        catch (Exception exp)
        {
            MessageBox.Show(exp.Message,
                            "Information",
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Information);
        }
        return null;
    }