如何在SQL Server中同时使用参数和函数

本文关键字:参数 函数 SQL Server | 更新日期: 2023-09-27 18:27:30

我对C#和SQL中的参数传递很陌生,但我知道实现它很关键。

场景是:

我已经在系统中内置了一个功能,但不知道如何编辑它,以便能够使用传递给它的参数。

我通过INSERT或UPDATE编辑的功能是:

   namespace SQLFunc
   {
   class SQLClass
   {
   public void SQLEdit(string var_SQLCommand)
    {
        using (SqlConnection myConn = new SqlConnection(this.SQLConnectString))
        using (SqlCommand var_command = new SqlCommand(var_SQLCommand, myConn))
        {
            myConn.Open();
            try
            {
                var_command.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                MessageBox.Show("An error occurred: " + ex.Message + " using SQL Query: " + var_SQLCommand, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                myConn.Close();
            }
        }
    }
    ...

我使用函数的常用命令是:

   using SQLFunc.SQLClass
   ....
   //command to variable
   var_Command = "UPDATE tbl_Table SET fld_Active = 'YES' WHERE fld_IDNo = " + var_A;
   //execute function
   var_SQLClass.SQLEdit(var_Command);

使用参数,我想去代码:

   using SQLFunc.SQLClass
   ....
   //command to variable
   var_Command = "UPDATE tbl_Table SET fld_Active = 'YES' WHERE fld_IDNo = @var_A_";
   // need to pass this entire line after the SQLCommand in the function SQLEdit
   var_Command.Parameters.AddWithValue("var_A_", var_A );
   var_SQLClass.SQLEdit(var_Command);

我希望能够在函数中使用参数传递。我可以传递变量var_A,但我希望我的代码能够满足适应性,比如它应该适用于一个字段(更新或插入)甚至10个字段(升级或插入),而不必在每次字段数量变化时更改函数的代码。

这是可以实现的吗?如果是,如何?

如何在SQL Server中同时使用参数和函数

以下是我的操作方法。

public class SqlClass
{
    public void ExecuteNonQuery(string sqlStatement, Dictionary<string, object> parameters)
    {
        using (SqlConnection connection = new SqlConnection(this.ConnectionString))
        {
            connection.Open();
            using (SqlCommand command = connection.CreateCommand())
            {
                command.CommandType = System.Data.CommandType.Text;
                command.CommandText = sqlStatement;
                foreach(var keyValuePair in parameters)
                {
                    command.Parameters.Add(new SqlParameter(keyValuePair.Key, keyValuePair.Value));
                }
                command.ExecuteNonQuery();
            }
        }
    }
}

您对SqlClass.ExecuteNonQuery()的调用将如下所示。

Dictionary<string, object> parameters = new Dictionary<string, object>
{
    { "@fld_Active", "Yes" },
    { "@fld_IDNo", 1 }
};
SqlClass sql = new SqlClass();
sql.ExecuteNonQuery("UPDATE tbl_Table SET fld_Active = @fld_Active WHERE fld_IDNo = @fld_IDNo", 
    parameters);

喜欢吗?

public void insert(string sql,Dictionary<stirng,object> parameters){
    using (SqlConnection myConn = new SqlConnection(this.SQLConnectString))
    using (SqlCommand var_command = new SqlCommand(var_SQLCommand, myConn))
    {
        myConn.Open();
        try
        {
            foreach(string name in parameters.Keys){
                var_Command.Parameters.AddWithValue(name, parameters[name] );
            }       
            var_command.ExecuteNonQuery();
        }
        catch (Exception ex)
        {
            MessageBox.Show("An error occurred: " + ex.Message + " using SQL Query: " + var_SQLCommand, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        finally
        {
            myConn.Close();
        }
    }
}

如果我理解正确,你会想要一些函数SQLEdit(command, /* params */),这样params就会"正常工作",并插入到查询中的正确位置。是这样吗?

如果是这样,那就很棘手了。请参阅,要使用参数化查询,必须提供SqlParameter对象。反过来,他们需要知道参数的SQL Server数据类型,而这是无法自动推断的。例如,DateTime可能是Time、DateTime或DateTime2之一。字符串可以是char、nchar、varchar、nvarchar、text、ntext。。。你明白了。

最好的(如果最详细的话)选择是让paramsparams SqlParameter parameters一样,并在使用它们的地方自己构建单独的参数。尝试构建自己的映射算法会让你付出高昂的代价。

如果您想要易用性,可以使用各种ORM中的任何一种(实体框架、Dapper等)。如果您想要原始SQL的性能,请准备编写一些代码。

为了让事情变得不那么冗长,您可以编写一个助手函数来为您创建参数对象,类似于以下内容,我在内存中完成了这项操作,但尚未进行测试:

public static SqlParameter Create(string name, SqlDbType type, object value)
{
    var p = new SqlParameter();
    p.ParameterName = name;
    p.SqlDbType = type;
    // If type is a fixed-length type, maybe set the correct string length here
    if (value == null)
    {
        p.SqlValue = DBNull.Value;
    }
    else
    {
        p.SqlValue = value;
    }
    return p;
}