Я точно не знаю, почему вы используете Request.Form
. Что-то вроде if (chkSpice.Checked)
было бы намного более читабельным.
Если вам нужно сохранить свой SQL в коде и не можете использовать хранимую процедуру, то это один из способов сделать это. Вы не принимаете пользовательский ввод и не передаёте его в SQL, поэтому нет риска внедрения SQL.
Если вы знаете, какие ваши стили и цвета будут названы в базе данных, оператор SQL IN
будет гораздо более эффективным.
string styles = String.Empty;
string colors = String.Empty;
if (chkTapestry.Checked)
styles = "'Tapestry'";
else if (chkRug.Checked)
styles += ",'Rug'";
if (chkBlack.Checked)
colors = "'Black'";
else if (chkBeige.Checked)
colors += ",'Beige'";
string sql = "SELECT * FROM [X]";
if (styles.Length > 0 && colors.Length > 0)
sql += String.Format(" WHERE [Style] IN ({0}) AND [Color] IN ({1})", styles, colors);
else if (styles.Length > 0)
sql += String.Format(" WHERE [Style] IN ({0})", styles);
else if (colors.Length > 0)
sql += String.Format(" WHERE [Color] IN ({0})", colors);
Выше приведен довольно ручной подход к сборке стилей и цветов и использует прискорбное жесткое кодирование имен стилей и цветов. Лучшим дизайном может быть:
- Выберите все цвета из базы данных. Сохраните их в DataTable.
- DataСвязать цвета DataTable с элементом управления CheckBoxList для отображения цветов на странице.
- Выберите все стили из базы данных. Сохраните их в другой таблице данных.
- Привязка стилей DataTable к элементу управления CheckBoxList для отображения стилей на странице.
Затем в PostBack:
- Перезагрузите ваши таблицы данных со значениями из базы данных. Примите небольшой риск того, что список цветов изменился с момента рендеринга вашей страницы, или сохраните DataTable в переменной Session между постами, чтобы уменьшить риск.
- Перезагрузите ваши стили DataTable.
- Перебирайте по цветам элементы CheckBoxList в цикле for. Для каждого выбранного элемента используйте индекс цикла for, чтобы получить тот же индекс строки из DataTable. Получите название цвета из DataRow и добавьте его в свой список цветов для использования в части
Color IN (...)
вашего предложения WHERE. Это гарантирует, что вы используете значение из вашей базы данных, а не значение, которое может быть подделано пользователем.
- Перебирайте элементы стиля CheckBoxList в цикле for, выполняя те же действия, что и цвета.
- Соберите предложение WHERE, как я делал в примере кода.
- Выполните запрос к вашей базе данных и обработайте набор результатов.
Пример кода:
protected DataTable dtColors
{
get
{
if (Session["fabrics-dtColors"] == null)
Session["fabrics-dtColors"] = FetchDataTable("SELECT DISTINCT Color FROM X ORDER BY Color");
return (DataTable)Session["fabrics-dtColors"];
}
}
protected DataTable dtStyles
{
get
{
if (Session["fabrics-dtStyles"] == null)
Session["fabrics-dtStyles"] = FetchDataTable("SELECT DISTINCT Style FROM X ORDER BY Style");
return (DataTable)Session["fabrics-dtStyles"];
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
cblColors.DataSource = dtColors;
cblColors.DataBind();
cblStyles.DataSource = dtStyles;
cblStyles.DataBind();
}
}
protected void btnSearch_OnClick(object sender, EventArgs e)
{
string colors = String.Empty;
string styles = String.Empty;
string sql = "SELECT * FROM [X]";
if (cblColors.SelectedIndex > -1)
{
for (int i = 0; i < cblColors.Items.Count; i++)
{
if (cblColors.Items[i].Selected)
{
colors += String.Format("'{0}',", dtColors.Rows[i][0]);
}
}
colors = colors.TrimEnd(',');
}
if (cblStyles.SelectedIndex > -1)
{
for (int i = 0; i < cblStyles.Items.Count; i++)
{
if (cblStyles.Items[i].Selected)
{
styles += String.Format("'{0}',", dtStyles.Rows[i][0]);
}
}
styles = styles.TrimEnd(',');
}
if (styles.Length > 0 && colors.Length > 0)
sql += String.Format(" WHERE [Style] IN ({0}) AND [Color] IN ({1})", styles, colors);
else if (styles.Length > 0)
sql += String.Format(" WHERE [Style] IN ({0})", styles);
else if (colors.Length > 0)
sql += String.Format(" WHERE [Color] IN ({0})", colors);
GetSearchResults(sql);
}