我在SQL Server中编写了这个过程:
ALTER proc [dbo].[cazacliente2]
(@vbusca nvarchar(60), @bo int)
as
if @bo= 1
begin
select idcliente, nome, endere, tel, pedido from Vw_Conscliente
where nome like @vbusca
end
if @bo = 2
begin
select idcliente, nome, endere, tel, pedido from Vw_Conscliente
where endere like @vbusca
end
if @bo = 3
begin
select idcliente, nome, endere, tel, pedido from Vw_Conscliente
where tel like @vbusca
end
if @bo = 4
begin
select idcliente, nome, endere, tel, pedido from Vw_Conscliente
where pedido like @vbusca
end
和asp.net中的代码:
{
string valorC = "%" + TextBox1.Text + "%"; numo = DropDownList1.SelectedValue;
string valorB = valorC.Replace(" ", "%");
switch (numo)
{
case "Nome": num3 = 1; break; case "Endereço": num3 = 2; break ;
case "Telefone": num3 = 3 ; break; case "Pedido": num3 = 4; break ;
}
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "cazacliente2";
SqlParameter valor = new SqlParameter("@vbusca", SqlDbType.NVarChar);
SqlParameter num = new SqlParameter("@bo",SqlDbType.Int );
valor.Value = valorB ; num.Value = num3 ;
cmd.Parameters.Add(valor); cmd.Parameters.Add(num);
if (conex1.State == ConnectionState.Closed)
{ conex1.Open(); }
cmd.Connection = conex1;
try
{
GridView1.EmptyDataText = "Nao se" + numo.ToString() +"encontraron registros";
GridView1.DataSource = cmd.ExecuteReader();
GridView1.DataBind();
}
catch (Exception ex)
{ throw ex; }
finally
{ conex1.Close(); }
}
当我传递字符串afonso pena
时,该过程返回所有数据就好了,但是当我传入afonso 60
时,它返回一个错误,当我传递一个不在数据库中的名称时它再次破裂,就像部分捕获不起作用。
答案 0 :(得分:1)
当您的问题涉及错误时,最好包含您在问题中看到的错误消息。由于在不知道错误消息的情况下很难调试,请尝试以下方法缩小问题的范围。
尝试重构代码以捕获任何可能的错误,然后再尝试数据绑定GridView
:
{
/*
* put the try at the top of the block to catch exceptions
* that may occur before you bind the GridView's datasource
*/
try
{
numo = DropDownList1.SelectedValue;
string valor = "%" + TextBox1.Text.Replace(" ", "%") + "%"; // no reason to NOT one-line this
/*
* This would probably be easier to maintain if DropDownList1
* was bound to an enumeration of these values:
* DataTextField="someTextField"
* DataValueField="someCorrespondingNumericField"
* If bound that like above, your switch statement becomes:
* Integer.Parse(DropDownList1.SelectedValue, numo);
* and numo then contains 1, 2, 3, or 4 thus eliminating the need for the variable num3.
*/
switch (numo)
{
case "Nome":
num3 = 1;
break;
case "Endereço":
num3 = 2;
break;
case "Telefone":
num3 = 3;
break;
case "Pedido":
num3 = 4;
break;
}
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "cazacliente2";
// add parameters and set values all at once
cmd.Parameters.Add("@vbusca", SqlDbType.NVarChar, 60).Value = valor;
cmd.Parameters.Add("@bo",SqlDbType.Int).Value = num3;
if (conex1.State == ConnectionState.Closed)
{
conex1.Open();
}
cmd.Connection = conex1;
GridView1.EmptyDataText = "Nao se " + numo.ToString() +" encontraron registros";
GridView1.DataSource = cmd.ExecuteReader();
GridView1.DataBind();
}
catch (Exception ex)
{
throw ex;
}
finally
{
conex1.Close();
}
}
此外,您的存储过程可以更清晰地编写:
ALTER PROCEDURE [dbo].[cazacliente2] (
@vbusca nvarchar(60)
, @bo int
)
AS
SELECT idcliente
, nome
, endere
, tel
, pedido
FROM Vw_Conscliente
WHERE CASE
WHEN @bo = 1 THEN nome
WHEN @bo = 2 THEN endere
WHEN @bo = 3 THEN tel
WHEN @bo = 4 THEN pedido
END LIKE @vbusca
答案 1 :(得分:0)
我会将外卡移到TSQL而不是C#。这样你就可以独立测试它。
您的定义显示最大长度为60.
@vbusca nvarchar(60)
从C#传递给SQL的参数是否大于该值?您应该在Visual Studio中的断点处查看局部变量,以确认这不是真的。
此外,替换参数内的空格意味着参数旁边的逻辑单词只需要按任何顺序匹配。这是你想要的吗?
'afonso 60'匹配'afsonso到商店去牛奶花费60美元'
查看MSDN的外卡使用情况: http://technet.microsoft.com/en-us/library/ms189454.aspx
我在下面使用了动态SQL,因为它减少了整体代码大小。
示例代码更改:
ALTER PROC [dbo].[cazacliente2] (@vbusca nvarchar(32), @bo int) AS
BEGIN
-- Local variables
DECLARE @statement VARCHAR(MAX);
DECLARE @field VARCHAR(MAX);
DECLARE @expression VARCHAR(MAX);
-- Make the expression (exact match of @vbusca)
SET @expression = '%' + REPLACE(@vbusca,'''', '''''') + '%';
-- Optional way (match words in @vbusca in order)
-- SET @expression = '%' + REPLACE(REPLACE(@vbusca,'''', ''''''), ' ', '%') + '%'
-- Which field
SELECT @field =
CASE @bo
WHEN 1 then 'nome'
WHEN 2 then 'endere'
WHEN 3 then 'tel'
WHEN 4 then 'pedido'
ELSE 'nome'
END;
-- Make up the dynamic SQL
SET @statement = 'select idcliente, nome, endere, tel, pedido ' +
' from Vw_Conscliente where ' + @field + ' like ' + @expression;
-- Execute the SQL statement
EXEC @statement;
END;
我将为我将来编写的任何动态TSQL添加警告建议。以下是如何处理注射问题的链接。
http://technet.microsoft.com/en-us/library/ms161953(v=sql.105).aspx
更新SP以通过减少搜索模式大小和处理参数内的单引号来处理问题。
答案 2 :(得分:0)
我认为这是迄今为止最好的解决方案,没有SQL注入,在传递无效的@bo时会处理,默认为nome。
ALTER PROCEDURE [dbo].[cazacliente2] (@vbusca nvarchar(60), @bo int)
AS
SELECT
idcliente
, nome
, endere
, tel
, pedido
FROM
Vw_Conscliente
WHERE
CASE
WHEN @bo = 1 THEN nome
WHEN @bo = 2 THEN endere
WHEN @bo = 3 THEN tel
WHEN @bo = 4 THEN pedido
ELSE nome
END LIKE @vbusca;