【问题标题】:C# and SQL parameters to prevent injections防止注入的 C# 和 SQL 参数
【发布时间】:2012-11-23 19:29:50
【问题描述】:

我想知道如何(在下面的代码中)确保 dataID 是下面传递的参数中的文本(或 varchar 或 int)?

public T ExecuteQuery<T>(Func<IDataReader, T> getResult, string query, params IDataParameter[] parameters)
    {
        using (SqlConnection conn = new SqlConnection(this.DefaultConnectionString))
        {
            conn.Open();

            // Declare the parameter in the query string
            using (SqlCommand command = new SqlCommand(query, conn))
            {
                foreach (var parameter in parameters)
                {
                    command.Parameters.Add(parameter);
                }

                command.Prepare();

                using (SqlDataReader dr = command.ExecuteReader())
                {
                    return getResult(dr);
                }
            }
        }
    }

    public string GetMySpecId(string dataId)
    {
        return ExecuteQuery(
            dr =>
            {
                if (dr.Read())
                {
                    return dr[0].ToString();
                }

                return string.Empty;
            },
            "select specId from MyTable where dataId = @dataId",
            new SqlParameter("dataId", dataId));
    }

我习惯这样编码:

command.Parameters.Add(new SqlParameter("key", SqlDbType.Text));

command.Prepare();

command.Parameters[0].Value = dataId;

在顶部的代码中,我如何将两个或多个参数传递给 ExecuteQuery?

【问题讨论】:

    标签: c# .net sql data-access-layer sqlparameter


    【解决方案1】:

    ExecuteQuery 已经接受了多个参数。它是一个ParamArray,这意味着它接受任意数量的参数并将它们转换为一个数组。

    例如,如果我有这样的功能:

    public int Sum(params int[] numbersToSum) { ... }
    

    我可以这样称呼它:

    Sum(1, 2, 5, 6, 1)
    

    在你的情况下,你可以这样称呼它:

    ExecuteQuery(
       dr => { //snip }, 
       query,
       new SqlParameter("dataId", dataId),
       new SqlParameter("anotherParm", parm2),
       new SqlParameter("anotherParm", parm3),
       ... );
    

    【讨论】:

    • 我怎么做才能让类型也被传递,比如 SqlDBType.NVarchar?
    • 假设您在System.Data.SqlClient 中使用SqlParameter 类,您可以在您传递的SqlParameter 对象(SqlDBType 属性)上设置该类。但是,SqlDBType 是从构造函数中给出的 .NET 对象推断出来的,因此您实际上不需要指定它:msdn.microsoft.com/en-us/library/0881fz2y.aspx
    【解决方案2】:

    代码使用了params 关键字,因此您似乎应该只编写额外的转义SQL 并继续将参数附加到方法的末尾。这是一个使用您的代码作为基础的示例。

    该链接提供了更完整的解释,但params 使您可以在方法签名的末尾具有可变数量的参数(只要它们是相同的类型)。它将落在这个params 变量中的所有最终参数放入一个数组中。

     return ExecuteQuery(
            dr =>
            {
                if (dr.Read())
                {
                    return dr[0].ToString();
                }
    
                return string.Empty;
            },
            "select specId from MyTable where dataId = @dataId and somethingelse = @else",
            new SqlParameter("dataId", dataId), 
            new SqlParameter("else", elseVar);
    

    【讨论】:

    • 它们的不同类型是什么?
    • 我也想传递不同的类型,也许我应该把它改成字典?
    猜你喜欢
    • 1970-01-01
    • 2019-06-03
    • 2010-09-23
    • 1970-01-01
    • 2011-06-12
    • 1970-01-01
    • 2013-04-18
    • 1970-01-01
    相关资源
    最近更新 更多