参数化SQL查询 - ASP.NET / C#

5

最近我了解到,为了避免SQL注入等安全问题,应该绝对使用参数化查询。这很好,我已经将其实现。

以下代码展示了我如何实现:

param1 = new SqlParameter();
param1.ParameterName = "@username";
param1.Value = username.Text;
cmd = new SqlCommand(str, sqlConn);
cmd.Parameters.Add(param1);

//and so on

但问题是,我有超过14个需要保存到数据库的变量,就像一个注册表格。如果我必须写14次来参数化每个变量,这看起来会非常混乱。有没有更动态的方法?比如使用for循环或其他方式,在循环中以某种方式对每个变量进行参数化?


您可以使用反射技术,从对象的属性名中创建参数名。当然,前提是 SQL 参数名与对象的属性名相同。 - unarity
6个回答

7

哦,这正是我在寻找的,谢谢。所以如果我理解正确的话,我只需要循环遍历它并更改参数即可? - Mana
@Mana,我不确定你所说的循环是什么意思?你有要添加到命令参数中的参数列表吗? - Habib
停止使用 AddWithValue。它不知道列的类型,所以它必须猜测。当它猜错时,你的代码开始表现得不可预测。 - Dour High Arch

2

这里是通过dapper提供的:

connextion.Execute(sql, new {
    username = username.Text,
    id = 123, // theses are all invented, obviously
    foo = "abc",
    when = DateTime.UtcNow
});

这个方法映射到ExecuteNonQuery,但还有其他方法,比如Query<T>(通过名称将数据绑定到每行的类型为T的对象中非常高效),Query(像Query<T>,但使用dynamic),以及一些其他方法(绑定多个网格或多个对象等)。所有这些方法都经过了荒谬的优化(IL级元编程),以使其尽可能快。


2
或者你可以尝试其他变体,比如这样。
command.Parameters.Add(new SqlParameter("Name", dogName));

我已经让你的方法也运作起来了,但我认为::Habibs::的方法看起来最简单,但知道还有其他方法总是很有趣的,谢谢,干杯。 - Mana

1

另一种技巧,您可以使用...

List<SqlParameter> lstPrm = new List<SqlParameter>();

 lstPrm.Add(new SqlParameter("@pusername", usernameValue ));
 lstPrm.Add(new SqlParameter("@pID", someidValue));
 lstPrm.Add(new SqlParameter("@pPassword", passwordValue));

最后,您可以迭代地将参数插入到您的命令对象中。

0
使用我的SqlBuilder类。它可以让你编写参数化查询,而无需创建参数或担心它的名称。你的代码将会像这样...
var bldr = new SqlBuilder( myCommand );
bldr.Append("SELECT * FROM CUSTOMERS WHERE ID = ").Value(myId);
//or
bldr.Append("SELECT * FROM CUSTOMERS NAME LIKE ").FuzzyValue(myName);
myCommand.CommandText = bldr.ToString();

你的代码将会更短,更易读。与连接查询相比,你甚至不需要额外的行。你需要的类在这里...

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;

public class SqlBuilder
{
private StringBuilder _rq;
private SqlCommand _cmd;
private int _seq;
public SqlBuilder(SqlCommand cmd)
{
    _rq = new StringBuilder();
    _cmd = cmd;
    _seq = 0;
}
public SqlBuilder Append(String str)
{
    _rq.Append(str);
    return this;
}
public SqlBuilder Value(Object value)
{
    string paramName = "@SqlBuilderParam" + _seq++;
    _rq.Append(paramName);
    _cmd.Parameters.AddWithValue(paramName, value);
    return this;
}
public SqlBuilder FuzzyValue(Object value)
{
    string paramName = "@SqlBuilderParam" + _seq++;
    _rq.Append("'%' + " + paramName + " + '%'");
    _cmd.Parameters.AddWithValue(paramName, value);
    return this;
}
public override string ToString()
{
    return _rq.ToString();
}
}

有趣的概念。但并没有真正回答这个问题。 - zanlok
很高兴你喜欢它。本质上的问题是“当我有14个参数时,如何使我的SQL代码看起来整洁?”我认为这个回答完全回答了这个问题。 - bbsimonbb

0
更好的方法是使用我的全新Visual Studio扩展程序。您可以在自己的文件中声明SQL参数。当您保存文件时,我的扩展程序将运行您的查询,并为您生成一个包装类以在运行时调用和一个结果类以访问您的结果,智能感知功能遍布整个程序。您将会看到您的SQL参数作为包装类Execute()方法的参数。您将不再需要编写任何C#参数代码、读取器代码、cmd或连接代码(除非您想自己管理)。一切都已经消失了 :-)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接