Comment gérer db violations de contrainte dans l'interface utilisateur?

Nous mettre en œuvre la majorité de nos règles de gestion dans la base de données, stockées procs.

Je ne peux jamais décider de la meilleure façon de transmettre des données des erreurs de violation de contrainte à partir de la base de données à l'interface utilisateur. Les contraintes dont je parle sont liés plus des règles métier de l'intégrité des données.

Par exemple, un db erreur du type "Impossible d'insérer une ligne de clé en double" est la même que la règle d'entreprise "vous ne pouvez pas avoir plus d'un Foo avec le même nom". Mais nous avons "mis en œuvre" dans son sens commun lieu: comme une contrainte unique, qui lève une exception lorsque la règle est enfreinte.

D'autres règles telles que "Vous n'êtes autorisés à 100 Foos par jour" ne pas provoquer des erreurs par dire, car ils sont normalement traitées par code personnalisé comme return empty dataset que le code de l'application vérifie et transmet retour à la couche d'interface utilisateur.

Et c'est là que le bât blesse. Notre code de l'interface utilisateur ressemble à ça (c'est AJAX.NET webservices code, mais n'importe quel framework ajax):

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
}

(Comme une note de côté: j'ai remarqué c'est ce que stackoverflow n'lorsque vous soumettez des commentaires trop rapidement: le serveur génère un HTTP 500 de réponse et de l'interface utilisateur l'attrape.)

Donc, vous voyez, nous sommes la manipulation des affaires de violation des règles dans les deux endroits, dont l'un (c'est à dire l'unique constaint d'erreur) est en train d'être traité comme un cas spécial pour le code qui est censé s'occuper de réel erreurs (pas des affaires de violations des règles), depuis .NET propage Exceptions tout le chemin jusqu'à la onError() gestionnaire.

Cela se sent mal. Mes options, je pense que sont:

  1. attraper la "violation de clé en double' exception à l'application, au niveau du serveur et convertir ce que c'est l'interface utilisateur s'attend à ce que la "règle d'entreprise violé" drapeau,
  2. préempter l'erreur (par exemple, avec un "select name from Foo where name = @Name") et retour quel qu'il soit, le serveur d'application s'attend à ce que la "règle d'entreprise violé" drapeau,
  3. dans le même ordre de grandeur que les 2): tirer parti de la contrainte unique construit dans la base de la couche et aveuglément insert into Foo, attraper toutes les exceptions et les convertir en ce que le serveur d'application s'attend à ce que la "règle d'entreprise violé" drapeau
  4. aveuglément insert into Foo (3) et de laisser cette Exception se propagent à l'interface utilisateur, plus l'application serveur de soulever des affaires de violations des règles comme de véritables Exceptions (contre 1). De cette façon, TOUTES les erreurs sont traitées dans l'interface utilisateur de la couche onError() (ou similaire) du code.

Ce que j'aime à propos de 2) et 3), c'est que les affaires de violations des règles sont "jetés" où ils sont mis en œuvre: dans la procédure stockée. Ce que je n'aime pas à propos de 1) et 3) je pense ils impliquent stupide vérifie comme "if error.IndexOf('duplicate key')", tout comme ce qui est dans la couche d'interface utilisateur actuellement.

Modifier: j'aime 4), mais la plupart des gens disent utiliser Exceptions seulement dans exceptionnelle circonstances.

Alors, comment voulez-vous les gens à gérer la multiplication des affaires de violations des règles jusqu'à l'interface utilisateur élégante?

OriginalL'auteur Crescent Fresh | 2009-02-22