C# 参数绑定:引擎盖下会发生什么?

C# 参数绑定:引擎盖下会发生什么?,c#,.net,sql,database,api,C#,.net,Sql,Database,Api,NET、Java和其他各种语言的高级数据库API通常提供称为预处理语句和参数绑定的技术,而不是向数据库服务器发送纯文本命令。我想知道的是,当您执行这样的语句时会发生什么: SqlCommand cmd = new SqlCommand("GetMemberByID"); cmd.CommandType = CommandType.StoredProcedure; SqlParameter param = new SqlParameter("@ID", memberID); para.DbType

NET、Java和其他各种语言的高级数据库API通常提供称为预处理语句和参数绑定的技术,而不是向数据库服务器发送纯文本命令。我想知道的是,当您执行这样的语句时会发生什么:

SqlCommand cmd = new SqlCommand("GetMemberByID");
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter param = new SqlParameter("@ID", memberID);
para.DbType = DbType.Integer;
cmd.Parameters.Add(param);
我知道这是最好的做法。SQL注入攻击通过这种方式最小化。但是当你执行这些语句时,到底会发生什么呢?最终结果仍然是SQL安全字符串吗?如果没有,最终结果是什么?这足以防止SQL注入攻击吗?

对准备好的语句提供了大量信息(这些信息应该适用于任何其他RDBMS)


基本上,您的语句是提前解析和处理的,参数是单独发送的,而不是与SQL代码一起处理。这消除了SQL注入攻击,因为SQL甚至在设置参数之前就被解析了。

如果使用MS SQL,请加载探查器,您将看到在使用参数化查询时生成了哪些SQL语句。下面是一个针对SQL Server 2005的示例(我使用的是Enterprise Library 3.1,但直接使用SqlParameters的结果是相同的):

string sql = "SELECT * FROM tblDomains WHERE DomainName = @DomName AND DomainID = @Did";
Database db = DatabaseFactory.CreateDatabase();
using(DbCommand cmd = db.GetSqlStringCommand(sql))
{
  db.AddInParameter(cmd, "DomName", DbType.String, "xxxxx.net");
  db.AddInParameter(cmd, "Did", DbType.Int32, 500204);

  DataSet ds = db.ExecuteDataSet(cmd);
}
这将产生:

exec sp[underscore]executesql N'SELECT * FROM tblDomains WHERE DomainName = @DomName AND DomainID = @Did',
  N'@DomName nvarchar(9),
  @Did int',
  @DomName=N'xxxxx.net',
  @Did=500204
您还可以在这里看到,如果引号字符作为参数传递,它们将相应地转义:

db.AddInParameter(cmd, "DomName", DbType.String, "'xxxxx.net");

exec sp[underscore]executesql N'SELECT * FROM tblDomains WHERE DomainName = @DomName AND DomainID = @Did',
  N'@DomName nvarchar(10),
  @Did int',
  @DomName=N'''xxxxx.net',
  @Did=500204

外行术语:如果发送了一条准备好的语句,那么DB将使用一个可用的计划,它不必在每次发送此查询时都重新创建一个计划,但只更改了参数的值。这与procs的工作方式非常相似,procs的另一个好处是,您只能通过procs授予权限,而不能授予底层表