你的设计并不是最优的;是否可以考虑将所有数据存储在链接到类别和子类别的中央表中?
有几个弱点;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();
}
}
}
}
}
不过,我要说的一个评论是,即使你实现了上面的任何一个例子,你仍然有一个大问题;您的数据访问代码、业务逻辑和演示代码现在都被整合到此页面背后的代码中。您将不得不在需要的任何地方重复此操作,从而导致大量重复,这在您需要修复错误时尤其成问题。
相反,您可能会考虑创建类或使用ORM为您处理所有这些工作,因此您改为请求 Architect 对象列表,或来自类或组件的 SomethingElse 列表,从而让 aspx 处理演示文稿. 这里还有一个关于为什么你可能不想使用 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();
}
}
实际上,现在其他人的工作是担心如何获取对象并收集它们,从而大大减少了您在代码中的代码。此外,您可以轻松地在各种界面中重用它!