Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当字符串有数字时,过程中断_C#_Asp.net_Sql Server_Visual Studio 2010 - Fatal编程技术网

C# 当字符串有数字时,过程中断

C# 当字符串有数字时,过程中断,c#,asp.net,sql-server,visual-studio-2010,C#,Asp.net,Sql Server,Visual Studio 2010,我已在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 beg

我已在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时,它返回一个错误,当我传递一个不在数据库中的名称时,它再次中断,这就像部件捕获不起作用一样。

我会将通配符移到TSQL,而不是C。这样,您可以独立测试它

您的定义显示最大长度为60

@vbusca nvarchar(60)
从C传递给SQL的参数是否大于该值?您应该在VisualStudio中查看断点上的局部变量,以确认这不是真的

此外,替换参数中的空格意味着参数中的逻辑字只需按任意顺序匹配即可。这是你想要的吗

“阿方索60”与“阿方索什么时候去商店买60美元的牛奶”相匹配

查看MSDN了解通配符的用法:

我在下面使用了动态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中添加一个警告提示。这里有一个关于如何处理注入问题的链接


更新了SP,通过减少搜索模式大小和处理参数内的单引号来处理问题。

当您的问题涉及错误时,最好将您看到的错误消息包含在问题中。由于在不知道错误消息的情况下很难进行调试,请尝试以下方法来缩小问题的范围

在尝试数据绑定GridView之前,请尝试重新构造代码以捕获任何可能的错误:

此外,您的存储过程可以编写得更干净一些:

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

我认为这是迄今为止最好的解决方案,没有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;

它会抛出什么错误?考虑到您只是在存储过程不返回任何数据的情况下得到一个错误,请在此特定条件下测试您的代码;它通过使用动态SQL来减少冗余。单元测试使用一个新的方法来测试正在中断的情况。这保证了PROC可以处理您的数据。然后调试C程序。如果您想查看@statement字符串,请在过程中使用PRINT。这是一个很好的例子,说明了为什么SqlInjection多年来一直是OWASP风险的头号您应该避免使用由用户输入生成的部分生成动态sql。除此之外,它确实有效:如果它是C语言中一个固定的下拉列表,那么如何获得SQL注入?另一方面,如果它是一个组合框,我会更改代码。我已经像狡猾的DBA所说的那样重新编写了该过程,并且无法找到返回的存储过程“从Vw_Conscliente选择idcliente、nome、endere、tel、pedido,其中nome像%ALEJANDRO%”。请尝试使用“EXEC sp_executesql@statement”。我没有为代码创建测试环境。我非常喜欢pete的解决方案,因为您不必担心SQL注入。但是,我要添加一个else子句。将5传递给代码时会发生什么?
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;