【问题标题】:parameterized sql query - asp.net / c#参数化 sql 查询 - asp.net / c#
【发布时间】:2012-11-28 07:44:07
【问题描述】:

所以我最近了解到我绝对应该使用参数化查询来避免 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参数名称与对象的属性名称相同。

标签: c# asp.net sql parameterized


【解决方案1】:

使用单行SqlParameterCollection.AddWithValue方法

cmd.Parameters.AddWithValue("@username",username.Text);

【讨论】:

  • 哦,正是我要找的东西,谢谢,所以如果我理解正确,我只是循环遍历它,然后更改参数?
  • @Mana,我不确定你所说的循环是什么意思?您有想要添加到命令参数的参数列表吗?
  • Stop using AddWithValue。它不知道列类型,所以它必须猜测。当它猜错时,您的代码开始出现不可预知的行为。
【解决方案2】:

或您可以尝试的其他变体

command.Parameters.Add(new SqlParameter("Name", dogName));

【讨论】:

  • 我的方法也有效,但我认为 ::Habibs:: 方法看起来最简单,但知道还有其他方法总是很有趣,谢谢,干杯
【解决方案3】:

给你...来自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 级元编程)都尽可能快。

【讨论】:

    【解决方案4】:

    另一种技术,你可以使用..

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

    添加您可以迭代的末尾以将参数插入您的command object

    【讨论】:

      【解决方案5】:

      使用我的 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();
      }
      }
      

      【讨论】:

      • 有趣的概念。不过,并没有真正回答 /this/ 问题。
      • 很高兴你喜欢它。本质上的问题是“当我有 14 个参数时,如何让我的 SQL 代码看起来整洁?”我认为这完全回答了这个问题??
      【解决方案6】:

      最好还是使用my shiny new Visual Studio extension。你在你的 sql 中声明你的参数,在它自己的文件中完好无损。我的扩展程序将在您保存文件时运行您的查询,并使您成为一个在运行时调用的包装类,以及一个用于访问您的结果的结果类,智能感知无处不在。您将看到您的 sql 参数作为包装类的 Execute() 方法的参数。您将永远不必在 C# 中编写另一行参数代码、阅读器代码、cmd 甚至连接(除非您想自己管理)。没了没了:-)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-06-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-03
        • 2011-10-10
        相关资源
        最近更新 更多