あなたのデザインは本当に最適ではありません。カテゴリとサブカテゴリの両方にリンクされた中央テーブルにすべてのデータを格納することを検討することは可能ですか?
いくつかの弱点があります。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();
}
}
事実上、オブジェクトを取得して収集する方法を心配するのは他の誰かの仕事になり、コード ビハインドに含まれるコードを大幅に削減できます。さらに、さまざまなインターフェイスで簡単に再利用できます。