Usuário com melhor resposta
SP não retorna valor

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()
RETURNE 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?
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 Snippetpublic 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
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 Snippetint 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 Snippetint indice = dtb.Rows.Count - 1;
Depois nos diga se funcionou.Abraços! -
Gulherme, eu já tinha testado mas não funcionou...
Acredito que o erro esteja aqui:
Code Snippetpublic 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...
-
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 Snippetpublic 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
-
Guilherme
MUITÍSSIMO OBRIGADO!
Funcionou perfeitamente!
A única ressalva é que tive que fazer o seguinte:
Code Snippettry
{
conSisAr.Open();
command.ExecuteNonQuery();
}
finally{
conSisAr.Close();
}
-
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!