none
SP não retorna valor RRS feed

  • Pergunta

  • Bom dia!

    Tenho a seguinte SP no meu banco:

     

     

    ALTER PROCEDURE dbo.RetornaID
     @NATUREZA Int,
     @FOLHA Char(5),
     @LIVRO Char(5),
     @ABERTURA Char(1),
     @ENCERRAMENTO Char(1),
     @SE Char(1),
     @DATA Char(10),
     @Identity int OUT
    AS
     Insert Into tblFichas (NATUREZA_ID, FOLHA, LIVRO, ABERTURA, ENCERRAMENTO, SE, DATA) Values (@NATUREZA, @FOLHA, @LIVRO, @ABERTURA, @ENCERRAMENTO, @SE, @DATA)
     SET @Identity = SCOPE_IDENTITY()
     RETURN

     

    E estou usando o seguinte código para acessar a SP:

     

    public DataTable AdicionaRegistro(string NATUREZA, string FOLHA, string LIVRO, string ABERTURA, string ENCERRAMENTO, string SE, string DATA)
      {
       SqlCommand command = new SqlCommand("RetornaID", conSisAr);
       command.CommandType = CommandType.StoredProcedure;
       command.Parameters.Add("@NATUREZA", SqlDbType.Int, 4, "NATUREZA_ID").Value = NATUREZA.ToString();
       command.Parameters.Add("@FOLHA", SqlDbType.Char, 5, "FOLHA").Value = FOLHA.ToString();
       command.Parameters.Add("@LIVRO", SqlDbType.Char, 5, "LIVRO").Value = LIVRO.ToString();
       command.Parameters.Add("@ABERTURA", SqlDbType.Char, 1, "ABERTURA").Value = ABERTURA.ToString();
       command.Parameters.Add("@ENCERRAMENTO", SqlDbType.Char, 1, "ENCERRAMENTO").Value = ENCERRAMENTO.ToString();
       command.Parameters.Add("@SE", SqlDbType.Char, 1, "SE").Value = SE.ToString();
       command.Parameters.Add("@DATA", SqlDbType.Char, 10, "DATA").Value = DATA.ToString();
       
       SqlParameter parameter = command.Parameters.Add("@Identity", SqlDbType.Int, 0, "ID");
       parameter.Direction = ParameterDirection.Output;

       
       try
       {
        conSisAr.Open();
        
        SqlDataAdapter adapter = new SqlDataAdapter(command);
        DataTable dt = new DataTable();
        adapter.Fill(dt);


        return dt;
       }
       finally
       {
         conSisAr.Close();     
       }
        
        }

     

     

    No entanto quando eu uso o método abaixo para recuperar os dados o resultado é nulo (dt não restorna nenhum valor...)

    DataTable dtb = AdicionaFicha.AdicionaRegistro(cmbIDAto.Text, txtFolha.Text, txtLivro.Text, "1", "0", "0", dtpDataAto.Text);
             
             int indice = dtb.Rows.Count;

             label1.Text = dtb.Rows[indice]["ID"].ToString();

     

     

    Erro apresentado (esse erro dá no DataTable dtb, quando eu tento executar):

     


    System.IndexOutOfRangeException was unhandled
      Message="Não há linha na posição 1."
      Source="System.Data"
      StackTrace:
           em System.Data.RBTree`1.GetNodeByIndex(Int32 userIndex)
           em System.Data.RBTree`1.get_Item(Int32 index)
           em System.Data.DataRowCollection.get_Item(Int32 index)
           em SisAr.frmFichas.btnCadastra_Click(Object sender, EventArgs e) na C:\Documents and Settings\Baroni\Meus documentos\Visual Studio 2008\Projects\SisAr\SisAr\frmFichas.cs:linha 399
           em System.Windows.Forms.Control.OnClick(EventArgs e)
           em System.Windows.Forms.Button.OnClick(EventArgs e)
           em System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
           em System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
           em System.Windows.Forms.Control.WndProc(Message& m)
           em System.Windows.Forms.ButtonBase.WndProc(Message& m)
           em System.Windows.Forms.Button.WndProc(Message& m)
           em System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
           em System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
           em System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
           em System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
           em System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
           em System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
           em System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
           em System.Windows.Forms.Application.Run(Form mainForm)
           em SisAr.Program.Main() na C:\Documents and Settings\Baroni\Meus documentos\Visual Studio 2008\Projects\SisAr\SisAr\Program.cs:linha 17
           em System.AppDomain._nExecuteAssembly(Assembly assembly, String[]args)
           em System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
           em Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
           em System.Threading.ThreadHelper.ThreadStart_Context(Object state)
           em System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
           em System.Threading.ThreadHelper.ThreadStart()
      InnerException:

     

    Alguém poderia dar alguma luz?

    quarta-feira, 29 de outubro de 2008 14:13

Respostas

  • Boa tarde, Tiago.

     

    Realmente o seu dt não vai retornar nenhuma linha... você não esta fazendo nenhum select na stored procedure.

     

    Para recuperar o valor do parametro de output tente o seguinte:

     

     

    Code Snippet

    public int AdicionaRegistro(string NATUREZA, string FOLHA, string LIVRO, string ABERTURA, string ENCERRAMENTO, string SE, string DATA)

    {

    SqlCommand command = new SqlCommand("RetornaID", conSisAr);

    command.CommandType = CommandType.StoredProcedure;

    command.Parameters.Add("@NATUREZA", SqlDbType.Int, 4, "NATUREZA_ID").Value = NATUREZA.ToString();

    command.Parameters.Add("@FOLHA", SqlDbType.Char, 5, "FOLHA").Value = FOLHA.ToString();

    command.Parameters.Add("@LIVRO", SqlDbType.Char, 5, "LIVRO").Value = LIVRO.ToString();

    command.Parameters.Add("@ABERTURA", SqlDbType.Char, 1, "ABERTURA").Value = ABERTURA.ToString();

    command.Parameters.Add("@ENCERRAMENTO", SqlDbType.Char, 1, "ENCERRAMENTO").Value = ENCERRAMENTO.ToString();

    command.Parameters.Add("@SE", SqlDbType.Char, 1, "SE").Value = SE.ToString();

    command.Parameters.Add("@DATA", SqlDbType.Char, 10, "DATA").Value = DATA.ToString();

    SqlParameter parameter = command.Parameters.Add("@Identity", SqlDbType.Int, 4, "ID");

    parameter.Direction = ParameterDirection.Output;

    try

    {

    conSisAr.Open();

    command.ExecuteNonQuery();

    return parameter.Value;

    }

    finally

    {

    conSisAr.Close();

    }

    }

     

     

     

    Note as partes que eu coloquei em vermelho, isso é o que você vai precisar alterar no seu código.

    Dessa forma, a sua função vai incluir um registro e, automaticamente, retornar o ID como inteiro.

     

    Tente e nos diga se funcionou.

     

    []´s

    quarta-feira, 29 de outubro de 2008 16:17

Todas as Respostas

  • Boa tarde Tiago, como vai?

     

    Bom... Você nos mostrou bastante código, então é difícil dizer exatamente aonde esta o problema.

    Tente dar uma olhada nessas linhas:

     

    Code Snippet

    int indice = dtb.Rows.Count;

    label1.Text = dtb.Rows[indice]["ID"].ToString();

     

     

     

    Se a sua tabela possui uma linha, o valor da variável "índice" vai ser igual a 1.

    Entretanto, o indexador da propriedade "Rows" da DataTable é base 0, ou seja. a primeira linha possui o índice 0, a segunda o índice 1 e assim por diante.

     

     

    O erro do tipo IndexOutOfRangeException nos diz exatamente isso (Não a linha na posição 1 - pois o registro esta na posição 0)

     

    tente fazer um teste trocando a linha q eu sitei por:

     

     

    Code Snippet

    int indice = dtb.Rows.Count - 1;

     
    Depois nos diga se funcionou.
     
    Abraços!
    quarta-feira, 29 de outubro de 2008 14:26
  •  

    Gulherme, eu já tinha testado mas não funcionou...

     

    Acredito que o erro esteja aqui:

     

    Code Snippet

    public DataTable AdicionaRegistro(string NATUREZA, string FOLHA, string LIVRO, string ABERTURA, string ENCERRAMENTO, string SE, string DATA)

    {

    SqlCommand command = new SqlCommand("RetornaID", conSisAr);

    command.CommandType = CommandType.StoredProcedure;

    command.Parameters.Add("@NATUREZA", SqlDbType.Int, 4, "NATUREZA_ID").Value = NATUREZA.ToString();

    command.Parameters.Add("@FOLHA", SqlDbType.Char, 5, "FOLHA").Value = FOLHA.ToString();

    command.Parameters.Add("@LIVRO", SqlDbType.Char, 5, "LIVRO").Value = LIVRO.ToString();

    command.Parameters.Add("@ABERTURA", SqlDbType.Char, 1, "ABERTURA").Value = ABERTURA.ToString();

    command.Parameters.Add("@ENCERRAMENTO", SqlDbType.Char, 1, "ENCERRAMENTO").Value = ENCERRAMENTO.ToString();

    command.Parameters.Add("@SE", SqlDbType.Char, 1, "SE").Value = SE.ToString();

    command.Parameters.Add("@DATA", SqlDbType.Char, 10, "DATA").Value = DATA.ToString();

    SqlParameter parameter = command.Parameters.Add("@Identity", SqlDbType.Int, 4, "ID");

    parameter.Direction = ParameterDirection.Output;

    try

    {

    conSisAr.Open();

    SqlDataAdapter adapter = new SqlDataAdapter(command);

    DataTable dt = new DataTable();

    adapter.Fill(dt);

    return dt;

    }

    finally

    {

    conSisAr.Close();

    }

    }

     

     

     

    Pelo que eu testei o "dt" está retornando vazio. Tenho que ver o por que ele não está retornando nenhum valor.

     

    Se você tiver alguma idéia... Big Smile

    quarta-feira, 29 de outubro de 2008 16:02
  • Boa tarde, Tiago.

     

    Realmente o seu dt não vai retornar nenhuma linha... você não esta fazendo nenhum select na stored procedure.

     

    Para recuperar o valor do parametro de output tente o seguinte:

     

     

    Code Snippet

    public int AdicionaRegistro(string NATUREZA, string FOLHA, string LIVRO, string ABERTURA, string ENCERRAMENTO, string SE, string DATA)

    {

    SqlCommand command = new SqlCommand("RetornaID", conSisAr);

    command.CommandType = CommandType.StoredProcedure;

    command.Parameters.Add("@NATUREZA", SqlDbType.Int, 4, "NATUREZA_ID").Value = NATUREZA.ToString();

    command.Parameters.Add("@FOLHA", SqlDbType.Char, 5, "FOLHA").Value = FOLHA.ToString();

    command.Parameters.Add("@LIVRO", SqlDbType.Char, 5, "LIVRO").Value = LIVRO.ToString();

    command.Parameters.Add("@ABERTURA", SqlDbType.Char, 1, "ABERTURA").Value = ABERTURA.ToString();

    command.Parameters.Add("@ENCERRAMENTO", SqlDbType.Char, 1, "ENCERRAMENTO").Value = ENCERRAMENTO.ToString();

    command.Parameters.Add("@SE", SqlDbType.Char, 1, "SE").Value = SE.ToString();

    command.Parameters.Add("@DATA", SqlDbType.Char, 10, "DATA").Value = DATA.ToString();

    SqlParameter parameter = command.Parameters.Add("@Identity", SqlDbType.Int, 4, "ID");

    parameter.Direction = ParameterDirection.Output;

    try

    {

    conSisAr.Open();

    command.ExecuteNonQuery();

    return parameter.Value;

    }

    finally

    {

    conSisAr.Close();

    }

    }

     

     

     

    Note as partes que eu coloquei em vermelho, isso é o que você vai precisar alterar no seu código.

    Dessa forma, a sua função vai incluir um registro e, automaticamente, retornar o ID como inteiro.

     

    Tente e nos diga se funcionou.

     

    []´s

    quarta-feira, 29 de outubro de 2008 16:17
  • Guilherme

     

    MUITÍSSIMO OBRIGADO!

     

    Funcionou perfeitamente!

     

    A única ressalva é que tive que fazer o seguinte:

     

    Code Snippet

    try

    {

    conSisAr.Open();

    command.ExecuteNonQuery();

    return Convert.ToInt16(parameter.Value);

    }

    finally

    {

    conSisAr.Close();

    }

     

     

    Valeu!
    quarta-feira, 29 de outubro de 2008 16:26
  • Exato =)

     

    Me desculpe pela questão do Cast. Como fiz o código de cabeça acabei esquecendo que o Value retorna um tipo Object.

     

    De qualquer forma, sugiro que vocë faça o cast com o Convert.ToInt32 e não Int16 pois você pode perder valores.

     

     

    grande abraço!

     

    quarta-feira, 29 de outubro de 2008 16:54