omo lidar com violações de restrição de banco de dados na interface do usuári
Implementamos a maioria de nossas regras de negócios no banco de dados, usando procs armazenado
Nunca consigo decidir a melhor maneira de passar os erros de violação de restrição de dados do banco de dados para a interface do usuário. As restrições de que estou falando estão mais ligadas às regras de negócios do que à integridade dos dado
Por exemplo, um erro de banco de dados como "Não é possível inserir linha de chave duplicada" é o mesmo da regra comercial "você não pode ter mais de um Foo com o mesmo nome". Mas nós o "implementamos" no local do senso comum: como uma restrição única que gera uma exceção quando a regra é violada.
Outras regras como "Você só tem permissão para receber 100 Foos por dia" não causam erros por assim dizer, uma vez que são manipulados normalmente por códigos personalizados comoreturn empty dataset
que o código do aplicativo verifica e passa de volta para a camada da interface do usuári
E aí jaz o X da questão. Nosso código da interface do usuário se parece com isso (este é o código de serviços da web do AJAX.NET, mas qualquer estrutura do ajax serve):
WebService.AddFoo("foo", onComplete, onError); // ajax call to web service
function onComplete(newFooId) {
if(!newFooId) {
alert('You reached your max number of Foos for the day')
return
}
// update ui as normal here
}
function onError(e) {
if(e.get_message().indexOf('duplicate key')) {
alert('A Foo with that name already exists');
return;
}
// REAL error handling code here
}
(Como observação lateral: Percebo que é isso que o stackoverflow faz quando você envia comentários muito rapidamente: o servidor gera umHTTP 500
resposta e a interface do usuário pega.)
Como você vê, estamos lidando com violações de regras de negócios em dois lugares aqui, um dos quais (isto é, o erro de restrição exclusivo) está sendo tratado como um caso especial para o código que deve tratarrea erros (não violações das regras de negócios), pois o .NET propaga exceções até oonError()
manipulador.
Isso parece errado. Minhas opções são:
capture a exceção 'violação de chave duplicada' no nível do servidor de aplicativos econverte para o que a interface do usuário espera, como a bandeira "regra de negócios violada", preempt o erro (digamos, com um"select name from Foo where name = @Name"
) e retorne o que o servidor de aplicativos espera como o sinalizador "regra de negócios violada", no mesmo estádio de 2): aproveite a restrição única incorporada na camada db e cegamenteinsert into Foo
, capturando todas as exceções e convertendo-o para o que o servidor de aplicativos espera, como o sinalizador "violação de regra comercial"blindlyinsert into Foo
(como 3) e deixe que a exceção se propague para a interface do usuário,mai fazer com que o servidor de aplicativos apresente violações das regras de negócios como reaisExceptions
(ao contrário de 1). Dessa forma, TODOS os erros são tratados no @ da camada da interface do usuáronError()
ódigo (ou similarO que eu mais gosto em 2) e 3) é que as violações das regras de negócios são "lançadas" onde eles são implementados: no processo armazenado. O que eu não gosto em 1) e 3) é que eupensa eles envolvem cheques estúpidos como"if error.IndexOf('duplicate key')"
, exatamente como está atualmente na camada da interface do usuário.
Edita: Eu gosto de 4), mas a maioria das pessoas diz para usarException
s apenas emexcepciona circunstâncias.
ntão, como você lida com a propagação de violações de regras de negócios até a interface do usuário de forma elegant