Wir implementieren die Mehrheit unserer Geschäftsregeln in der Datenbank mit gespeicherten Procs.Wie behandelt man DB-Constraint-Verletzungen in der Benutzeroberfläche?
Ich kann nie entscheiden, wie Fehler bei der Dateneinschränkungsverletzung am besten von der Datenbank an die Benutzerschnittstelle übergeben werden. Die Einschränkungen, über die ich spreche, sind mehr an Geschäftsregeln als an Datenintegrität gebunden.
Zum Beispiel ist ein DB-Fehler wie "Kann doppelte Schlüsselzeile nicht einfügen" dasselbe wie die Geschäftsregel "Sie können nicht mehr als ein Foo mit dem gleichen Namen haben". Aber wir haben es an der gebräuchlichsten Stelle implementiert: als eine einzigartige Einschränkung, die eine Ausnahme auslöst, wenn die Regel verletzt wird.
Andere Regeln wie "Sie dürfen nur 100 Foos pro Tag verwenden" verursachen keine Fehler per-say, da sie ordnungsgemäß von benutzerdefiniertem Code wie behandelt werden, den der Anwendungscode sucht und an den zurückgibt UI-Schicht.
Und darin liegt der Haken. Unser ui Code sieht wie folgt aus (dies ist AJAX.NET einen Web Service-Code, aber jeder Ajax-Framework tun wird):
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
}
(Als Randbemerkung: Ich stelle fest, das ist, was tut, wenn Sie Stackoverflow Kommentare einreichen zu schnell: der Server generiert eine HTTP 500
Antwort und die ui fängt es ab.)
So sehen Sie, wir behandeln Verstöße gegen die Geschäftsregeln an zwei Stellen hier, von denen einer (dh der einzigartige Constaint-Fehler) als Sonderfall behandelt wird der Code, der echte Fehler behandelt (nicht Verstöße gegen die Geschäftsregeln), da .NET Exceptions bis zum onError()
Handler propagiert.
Das fühlt sich falsch an. Meine Optionen Ich denke, sind:
- fängt die ‚doppelte Schlüsselverletzung‘ Ausnahme bei der App-Server-Ebene und konvertieren es, was auch immer es die ui erwartet als „Business-Regel verletzt“ Flagge,
- preempt der Fehler (sagen wir, mit einem
"select name from Foo where name = @Name"
) und zurück, was auch immer der App-Server erwartet als die "Business Rule verletzt" -Flag, - im selben Stadion wie 2): Hebel die einzigartige Integritätsbedingung in die dB-Schicht integriert und blind
insert into Foo
, irgendwelche Ausnahmen abfangen und es in alles umwandeln, was die App bedient r erwartet als die Flag „Geschäftsregel verletzt“ - blind
insert into Foo
(wie 3) und lassen Sie die Ausnahme von der ui propagieren, Plus die App-Server erhöht Geschäft Regelverletzungen als echteExceptions
hat (im Gegensatz zu 1 gegenüber). Auf diese Weise werden ALLE Fehler in demonError()
(oder ähnlichem) Code der ui-Schicht behandelt.
Was Ich mag über 2) und 3) ist, dass die Geschäftsregelverletzungen „geworfen“ werden wo sie umgesetzt werden: in der gespeicherten proc. Was ich an 1) und 3) nicht mag, ist denke sie beinhalten dumme Schecks wie "if error.IndexOf('duplicate key')"
, genau wie in der UI-Schicht derzeit.
bearbeiten: Ich mag 4), aber die meisten Leute sagen, Exception
s nur in außergewöhnlichen Umständen zu verwenden.
Also, wie gehen Sie Menschen mit der Verbreitung von Verstößen gegen die Geschäftsregeln bis zur UI elegant?
Ich wünschte, die Person, die diese und http://stackoverflow.com/questions/581994/-net-coding-standards-and-framework-for-a-web-service/582429#582429 downvoted würde geben einen Grund. Zwei sehr unterschiedliche Antworten, gleiches Ergebnis, innerhalb einer Minute. –
Der Code, der schließlich 'RAISERROR' aufruft, muss immer noch eine" dumme Überprüfung "wie' CHARINDEX ('duplicate key', @errorMessage)> 0' durchführen, und ich habe diese Frage gefunden, weil mein Beispielszenario einen * zwei * möglichen eindeutigen Schlüssel enthält Constraint-Verletzungen, und ich war neugierig, ob es einen Weg gab zu bestimmen, welcher Schlüssel verletzt wurde, ohne nach den Namen der Schlüssel oder den Namen der relevanten Spalten zu suchen. –