Bom dia nobres amigos, venho por aqui mais para documentar algo que ocorreu em um dos meus trabalhos e gostaria de compartilhar e saber da opinião de vocês.
Tenho uma aplicação legada em Windows Forms que faz controle de pasta em um determinado arquivo de uma empresa.
Em um dado momento foi necessário dar uma manutenção em determinado ponto aonde era preciso realizar um INSERT e logo após um UPDATE em tabelas diferentes. O erro vinha exatamente desse método que tentava executar uma transação mas a mesma não conseguia ser executada. O Erro apresentado era o ORA-00933: SQL command not properly ended
Resolvi vir ate a comunidade e documenta-la pois procurei em diversos fóruns e não achei referencias que pudessem solucionar esse problema.
Irei postar o código inicial abaixo que apresentava tal erro:
public String GravaRequisicao(Requisicao req, Usuario usuario)
{
Setor setor = new Setor();
int LinhasTotais = 0;
string mensagem = "";
StringBuilder strSQL = new StringBuilder();
StringBuilder strSQLU = new StringBuilder();
try
{
AbreConexao();
OracleTransaction transacao;
transacao = Con.BeginTransaction();
foreach (Pasta p in req.Pastas)
{
//Grava a requisição
strSQL.Append("INSERT INTO REQPASTAS ");
strSQL.Append("(NUMPASTA, DTRETIRADA, DTDEVPREV, DTDEVOLUCAO, IDREQUERENTE, ");
strSQL.Append("CODSETOR, NUMREQ, IDUSUARIO, SITPASTA, SITREQ) ");
strSQL.Append("VALUES (");
strSQL.Append(p.CodigoPasta.ToString());
strSQL.Append(", TO_DATE('");
strSQL.Append(p.DataRetirada.ToString().Substring(0,10));
strSQL.Append("', 'DD/MM/YYYY'), TO_DATE('");
strSQL.Append(p.DataPrevisaoDevolucao.ToString().Substring(0, 10));
strSQL.Append("', 'DD/MM/YYYY'), ");
strSQL.Append("NULL"); // Data de Devolução não é preenchida neste momento.
strSQL.Append(", ");
strSQL.Append(req.Requerente);
strSQL.Append(", '");
strSQL.Append(p.Setor);
strSQL.Append("', ");
strSQL.Append(p.CodigoRequisicao);
strSQL.Append(", ");
strSQL.Append(usuario.IdUsuario);
strSQL.Append(", ");
strSQL.Append("'A'");
strSQL.Append(", ");
strSQL.Append("'A'");
strSQL.Append(")");
Cmd = new OracleCommand(strSQL.ToString(), Con)
{
CommandType = System.Data.CommandType.Text
};
int LinhasIncluidas = Cmd.ExecuteNonQuery();
//Aloca a pasta com tituação = 1
strSQLU.Append("UPDATE ARQPASTAS ");
strSQLU.Append("SET STATUS = '1' ");
strSQLU.Append("WHERE NUMPASTA = ");
strSQLU.Append(p.CodigoPasta);
Cmd = new OracleCommand(strSQLU.ToString(), Con)
{
CommandType = System.Data.CommandType.Text
};
int LinhasAlteradas = Cmd.ExecuteNonQuery();
Cmd.Transaction = transacao;
LinhasTotais += LinhasIncluidas;
if (LinhasIncluidas != LinhasAlteradas)
{
transacao.Rollback();
mensagem = "Requisição não gravada. Contactar a TI.";
}
else
{
if (LinhasTotais == req.Pastas.Count())
{
mensagem = "1";
transacao.Commit();
}
}
}
}
catch (Exception ex)
{
RegistraErro(new Error(new StackTrace(true), ex, strSQL.ToString() + " " + strSQLU.ToString()));
mensagem = "Erro no ORACLE. Contate a TI.";
}
finally
{
FecharConexao();
}
return mensagem;
}
Segue o código com as modificações que julgo correto e gostaria da opinião dos senhores quanto ao uso de Transação dentro do Windows Forms desconsiderando detalhes de modelagem de dados:
public String GravaRequisicao(Requisicao req, Usuario usuario)
{
Setor setor = new Setor();
int LinhasTotais = 0;
string mensagem = "";
StringBuilder strSQL = new StringBuilder();
StringBuilder strSQLU = new StringBuilder();
try
{
AbreConexao();
OracleTransaction transacao;
foreach (Pasta p in req.Pastas)
{
//Limpando StringBuilder anterior
strSQL.Clear();
strSQLU.Clear();
transacao = Con.BeginTransaction();
Cmd = new OracleCommand();
Cmd.Connection = Con;
Cmd.Transaction = transacao;
//Grava a requisição
strSQL.Append("INSERT INTO REQPASTAS ");
strSQL.Append("(NUMPASTA, DTRETIRADA, DTDEVPREV, DTDEVOLUCAO, IDREQUERENTE, ");
strSQL.Append("CODSETOR, NUMREQ, IDUSUARIO, SITPASTA, SITREQ) ");
strSQL.Append("VALUES (:CODIGOPASTA, ");
strSQL.Append("TO_DATE(:DATARETIRADA, 'DD/MM/YY'),");
strSQL.Append("TO_DATE(:DATAPREVDEV, 'DD/MM/YY'),");
strSQL.Append("NULL,"); // Data de Devolução não é preenchida neste momento.
strSQL.Append(":REQUERENTE,");
strSQL.Append(":SETOR, ");
strSQL.Append(":NUMREQ, ");
strSQL.Append(":IDUSUARIO, ");
strSQL.Append("'A',");
strSQL.Append("'A'");
strSQL.Append(")");
Cmd.CommandText = strSQL.ToString();
FuncoesDAL fd = new FuncoesDAL();
Cmd.Parameters.Add("CODIGOPASTA",OracleDbType.Int32).Value = p.CodigoPasta;
Cmd.Parameters.Add("DATARETIRADA",OracleDbType.Varchar2).Value = fd.FormataDataInsertOracle(p.DataRetirada);
Cmd.Parameters.Add("DATAPREVDEV",OracleDbType.Varchar2).Value = fd.FormataDataInsertOracle(p.DataPrevisaoDevolucao);
Cmd.Parameters.Add("REQUERENTE", OracleDbType.Varchar2).Value = req.Requerente.ToString();
Cmd.Parameters.Add("SETOR", OracleDbType.Varchar2).Value = p.Setor.ToString() ;
Cmd.Parameters.Add("NUMREQ", OracleDbType.Varchar2).Value =p.CodigoRequisicao.ToString();
Cmd.Parameters.Add("IDUSUARIO", OracleDbType.Int32).Value = usuario.IdUsuario;
int LinhasIncluidas = Cmd.ExecuteNonQuery();
Cmd.Parameters.Clear();
//Aloca a pasta com Situação = 1
strSQLU.Append("UPDATE ARQPASTAS ");
strSQLU.Append("SET STATUS = '1' ");
strSQLU.Append("WHERE NUMPASTA = :NUMPASTA");
Cmd.CommandText = strSQLU.ToString();
Cmd.Parameters.Add("NUMPASTA", OracleDbType.Int32).Value = p.CodigoPasta;
int LinhasAlteradas = Cmd.ExecuteNonQuery();
LinhasTotais += LinhasIncluidas;
if (LinhasIncluidas != LinhasAlteradas)
{
transacao.Rollback();
mensagem = "Requisição não gravada. Contactar a TI.";
}
else
{
mensagem = "1";
transacao.Commit();
}
}
}
catch (Exception ex)
{
RegistraErro(new Error(new StackTrace(true), ex, strSQL.ToString() + " " + strSQLU.ToString()));
mensagem = "Erro no ORACLE. Contate a TI.";
}
finally
{
FecharConexao();
}
return mensagem;
}
No aguardo as críticas para juntos podermos crescer
Abraços a todos
Max