如何在ASP中的SQL连接中传递修改后的表名

时间:2012-07-04 10:47:58

标签: c# asp.net .net sql-server-2008 sql-server-2008-r2

我在asp.net中使用SQL Server 2008作为我的数据库。我在点击<a>标签到网络表单时传递了表名。那么如何才能实现这一点,当我点击任何链接时,它会根据收到的值更改其SQL查询?

例如:

 <li class="last">
    <a href="category.aspx?cat=Architect&sub=Architects">Item 1.1</a>
 </li>

此处cat包含表名,sub包含条件名称。

另一方面我正在做:

SqlConnection con=new SqlConnection("Data Source=ANURAG-PC;Initial Catalog=dbPortal;Persist Security Info=True;User ID=sa;Password=anurag");
SqlDataAdapter da;
DataSet ds=new DataSet();
static DataTable dt = new DataTable();

protected void Page_Load(object sender, EventArgs e) 
{
   if (IsPostBack == false)
   {
      string s = Request.QueryString["cat"];
      string s1 = Request.QueryString["sub"];

      da = new SqlDataAdapter("select * from Architect where subcategory3='" + s1 + "'",con);
      da.Fill(ds,"tab");
      dt = ds.Tables["tab"];
      DataGrid1.DataSource = dt;
      DataGrid1.DataBind();
   }
}

所以我只想要提供表名Architect,我只想通过s - 我怎么能这样做?

4 个答案:

答案 0 :(得分:1)

我建议您考虑其他解决方案,因为您当前正在进行的操作将导致非常简单的SQL注入,并且您的数据库将面临巨大风险。我建议你有一个所有表的枚举,并在查询字符串而不是表名中传递表的id,并且你应该确保条件字符串在进行字符串连接之前从任何sql注入有效

答案 1 :(得分:0)

da = new SqlDataAdapter("select * from " + s + " where subcategory3='" + s1 + "'",con);

答案 2 :(得分:0)

您的设计并不是最佳选择;是否可以考虑将所有数据存储在链接到Category和SubCategory的中央表中?

有几个弱点;任何sql的字符串连接都会让你对SqlInjection攻击开放。例如,即使您从下拉列表中选择值,客户端脚本仍然可以修改组合框中的值,或者攻击者只需将数据发布到服务器端事件处理程序。

此外,必须从多个表中获取数据意味着您可能必须在结果中处理不同的模式;如果你期望这样(即一些表将有比其他表更多的列),那么你可以适当地处理它。

您的查询将变为类似于:

protected void Page_Load(object sender, EventArgs e) 
{
   if (IsPostBack == false)
   {
      string s = Request.QueryString["cat"];
      string s1 = Request.QueryString["sub"];

      if(String.IsNullOrEmpty(s) || String.IsNullOrEmpty(s1)) { return; } //Improve Validation and error reporting

      using(SqlConnection conn = new SqlConnection("Data Source=ANURAG-PC;Initial Catalog=dbPortal;Persist Security Info=True;User ID=sa;Password=anurag"))
      {
        using(SqlCommand command = new SqlCommand(conn))
        {
            command.CommandType = CommandType.Text;
            command.CommandText = "SELECT * FROM Table WHERE Category = @Category AND SubCategory = @SubCategory";

            command.Parameters.Add(new SqlParameter() { Type = SqlDbType.String, Name = "@Category", Value = s });
            command.Parameters.Add(new SqlParameter() { Type = SqlDbType.String, Name = "@SubCategory", Value = s1 });

            conn.Open();

            using(SqlDataReader reader = command.ExecuteReader())
            {
                DataTable data = new DataTable("MyData");
                data.Load(reader);
                DataGrid1.DataSource = data;
                DataGrid1.DataBind();
            }

        }
      }
   }
}

如果您坚持使用原始模型,那么您可能希望将表名列入白名单,以便您可以坚持使用参数化查询:

protected void Page_Load(object sender, EventArgs e) 
{
   if (IsPostBack == false)
   {
      string s = Request.QueryString["cat"];
      string s1 = Request.QueryString["sub"];

      if(String.IsNullOrEmpty(s) || String.IsNullOrEmpty(s1)) { return; } //Improve Validation and error reporting

      using(SqlConnection conn = new SqlConnection("Data Source=ANURAG-PC;Initial Catalog=dbPortal;Persist Security Info=True;User ID=sa;Password=anurag"))
      {
        using(SqlCommand command = new SqlCommand(conn))
        {
            command.CommandType = CommandType.Text;

            switch(s)
            {
                case "Architect":
                    command.CommandText = "SELECT * FROM Architect WHERE SubCategory = @SubCategory";
                    break;
                case "SomethingElse":
                    command.CommandText = "SELECT * FROM SomethingElse WHERE SubCategory = @SubCategory";
                    break;
                default:
                    return; //Again, improve error handling
            }

            command.Parameters.Add(new SqlParameter() { Type = SqlDbType.String, Name = "@SubCategory", Value = s1 });

            conn.Open();

            using(SqlDataReader reader = command.ExecuteReader())
            {
                DataTable data = new DataTable("MyData");
                data.Load(reader);
                DataGrid1.DataSource = data;
                DataGrid1.DataBind();
            }

        }
      }
   }
}

我要做的一个评论是,即使你实施上述任何一个例子,你仍然有一个大问题;您的数据访问代码,业务逻辑和演示文稿代码现在都被包含在此页面的代码中。您将不得不在需要的任何地方重复此操作,从而导致大量重复,这在您需要修复错误时尤其成问题。

相反,您可以consider creating classes或使用ORM来处理所有这些工作,因此您可以从类或组件请求Architect对象列表或SomethingElse列表,从而让aspx处理演示文稿。还有discussion here关于您想要使用ORM的原因。

如果您遵循此路线,您的代码可能会变成:

protected void Page_Load(object sender, EventArgs e) 
{
   if (IsPostBack == false)
   {
      string s = Request.QueryString["cat"];
      string s1 = Request.QueryString["sub"];
      //Still do validation on s and s1

      ObjectFactory of = new ObjjectFactory();
      DataGrid1.DataSource = ObjectFactory.GetObjects(s, s1);
      DataGrid1.DataBind();
    }
 }

实际上,现在是别人的工作,担心如何获取对象并收集它们,大大减少了代码背后的代码。此外,您可以轻松地在各种界面中重复使用它!

答案 3 :(得分:-1)

喜欢这个吗?

SqlConnection con=new SqlConnection("Data Source=ANURAG-PC;Initial Catalog=dbPortal;Persist Security Info=True;User ID=sa;Password=anurag");
    SqlDataAdapter da;
    DataSet ds=new DataSet();
    static DataTable dt=new DataTable();


        protected void Page_Load(object sender, EventArgs e) 
        {
            if (IsPostBack == false)
            {
                string s = Request.QueryString["cat"];
                string s1 = Request.QueryString["sub"];


                da = new SqlDataAdapter("select * from '"+s+"' where subcategory3='" + s1 + "'",con);
                da.Fill(ds);
                dt = ds.Tables[0];
                DataGrid1.DataSource = dt;
                DataGrid1.DataBind();

            }



        }