StrataFrame Forum

Integridade Referencial

http://forum.strataframe.net/Topic29389.aspx

By Marcio Valerio Silva - 1/19/2011

Eu preciso adicionar algumas restrições de integridade para impedir que sejam deletados registros que sejam chaves estrangeiras em outras tabelas. Até aí tudo bem no Deployment Database do SF é moleza!

Mas como capturar as excessões causadas por essa excessão e tratá-las mostrando uma mensagem mais amigavel ao usuário Final, sem que apareceça aquela tela do SF de tarja vermelha que parece que o "mundo vai acabar".

Não achei uma maneira até agora. 
By Ivan George Borges - 1/20/2011

Dê uma olhada no seu AppMain.vb/Program.cs na Sub UnhandledExceptionFound.

Lá você pode por exemplo setar e.Handled = True e manipular a excessão como desejar.
By Marcio Valerio Silva - 4/21/2011

Olá Ivan Ainda estou com uma dificuldade.

Dentro do Form onde é que eu consigo pegar a string da excessão. Eu já tentei de diversas formas e até agora eu não consegui.

Alguns clientes não aceitam muito bem a mensagem em ingles do banco de dados e eu realmente preciso fazer algo mais simplificado ao diaer ao cliente que é uma questão de integridade referencial e não um erro comum.

Hoje aparece assim a mensagem:

SqlException
  The DELETE statement conflicted with the REFERENCE constraint "NovosTitulos". The conflict occurred in database "m2enterprise", table "dbo.RenegociacaoNovosTitulos", column 'CtaReceberId'.
The statement has been terminated.


E eu gostaria simplesmente de mostrar a mensagem dizendo que trata-se de uma informação constante na tabela "xxxx" do banco de dados

Se você puder me passar o meio eu agradeço muito!

Um bom feriado e até mais.

At,

Marcio Valerio da Silva
By Marcio Valerio Silva - 4/24/2011

Olá Ivan!

Olha o melhor que eu consegui até agora foi o seguinte:

Criei um código no BO assim:

public string DeleteRegistroIR(int _id)
{
string _retorno = string.Empty;
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.AppendFormat("Delete {0} where clientesId = {1}", this.TableName, _id.ToString());
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = sqlBuilder.ToString();
try
{
this.ExecuteNonQuery(cmd);
}
catch (SqlException ex)
{
_retorno = ex.Message;
}
}
return _retorno;
}


E adicioneu no evento  BeforeDelete para parar a execução da deleção do form conforme abaixo:


private void frmClientes_BeforeDelete(MicroFour.StrataFrame.Business.BeforeDeleteEventArgs e)
{
e.Cancel = true;
string _mensagem = clientesBO1.DeleteRegistroIR(clientesBO1.ClientesId);
if (!string.IsNullOrEmpty(_mensagem))
{
MessageBox.Show("Exclusão não Permitida! \n Há Informações Vinculadas em Outros Registros!", "", MessageBoxButtons.OK, MessageBoxIcon.Stop);
}
}
}


Desta forma quando o BO me retorna alguma mensagem informo o usuário que o registro não será excluido, pois existe informação em outra tabela relacionada.

Outro problema é que desta forma eu não consegui separar a tabela que gerou o conflito afim de informar o usuário, para que mesmo assim ele queira excluir o registro ele possa excluir as informações de tabelas referenciadas e depoi concluir a exclusão.

No código acima eu não gostei que após a confimação de deleção mesmo se o usuário não confirmar a deleção é excutado o evento BeforeDelete eu acredito que não deveria pois não foi confirmado a deleção pelo usuário.

Por favor me passe a forma correta de executar este procedimento.

 

By Ivan George Borges - 4/25/2011

Olá Márcio.

Primeiro, se você estiver procurando lidar com a mensagem de excessão, como eu te disse, deveria dar uma olhada no UnhandledExceptionFound no seu Program.cs. Neste ponto, você pode capturar a mensagem e lidar com ela como quiser. Eu, por exemplo, monto um form onde coloco a mensagem que foi capturada e um diálogo com o usuário tentando traduzir o que aconteceu. Além disto, mando automaticamente esta mensagem para nosso email de suporte, com identificação do erro e quando e onde ocorreu. Se der uma olhada no Help, vai encontrar explicação sobre isto em Application Framework -> Application -> WinForms -> Appmain.vb (program.cs) File -> UnhandledExceptionFound().

Quanto a lidar com a situação de não permitir uma exclusão caso o registro corrente já tenha sido utilizado como uma ForeignKey em outra tabela, o ideal seria que criasse um BusinessObject Base para sua aplicação e colocasse o código para lidar com isto no BeforeDelete do mesmo. Depois, deveria criar todos os seus BO herdando deste seu BaseBO.

Nos seus forms, caso não queira que a mensagem de Exclusão apareça automaticamente, deveria configurá-los com AutoShowDeleteConfirmation = False. E mais uma vez, se espera ter isto como padrão em todos os seus forms, deveria criar um Form Base, configurar as propriedades que queira neste form e depois fazer com que todos os forms de sua aplicação herdem de seu BaseForm.

No seu BaseBO, no BeforeDelete, a propriedade This.TableName te dirá em qual tabela o usuário está tentando excluir e a partir daí você pode testar nas outras tabelas onde este registro pode ter sido utilizado se existe a ForeignKey da tabela corrente, e em caso positivo, informar ao usuário inclusive onde foi usado.

Então, se não foi usado, você mostra uma mensagem de confirmação de Exclusão, já que a automática foi desligada, e pega a resposta do cliente confirmando a Exclusão.

No fim, se encontrou o registro usado em outra tabela ou se o usuário não confirmou a exclusão, você faz "e.Cancel = True", isto cancelará a exclusão.

O BeforeDelete sempre será executado e é nele que você vai testar se o Delete realmente deve ser obedecido.
By Marcio Valerio Silva - 4/25/2011

Ola Ivan,

Muito Obrigado por enquanto, gostei da informação de envio da mensagem para o e-mail. Vou adotar algo parecido aqui.

Desculpe incomodar, mas foi necessário nesse momento.

Até mais.
By Ivan George Borges - 4/25/2011

Que é isto! De nada, não é incômodo nenhum.

Vai postando que a gente vai tentando ajudar. Uma dica, se conseguir postar em Inglês, mesmo que seja usando aqueles tradutores do Google, a sua pergunta poderá ser lida por todo mundo. Às vezes eu não estou aqui no momento e então outra pessoa pode tentar te ajudar também. Mas se não se sentir à vontade para isto, pode ir colocando em Português que sempre que dá eu entro e tento responder.

Abração.