Designfrage: Trigger & Fremdschlüssel oder Programmlogik



  • Stehe momentan vor der Frage, ob ich referentielle Vorgänge, wie z.B. löschen von Abhängigkeiten auf der Datenbank realisiere (über Foreign Keys etc), oder ob das eher in die Clientlogik gehört. Auf Clientebene wäre das Ganze sicher schicker zu transportieren, aber richtig "wasserdicht" ist es mMn nur in der DB. Wie macht ihr es? Client oder DB oder beides a la "DB als letzte Sicherheit" ?



  • Das kommt drauf an. Sowas wie Foreign Keys ist ja Standard, das macht man auf jeden Fall in der Datenbank, wenn sich das anbietet. Wenn die Logik aber komplexer wird, dann bin ich kein Fan davon, sie in die Datenbank zu verfrachten und mache das lieber in der Anwendung.



  • Ich bin ein Freund davon, möglichst alles an Anwendungslogik in der Anwendung zu haben. Dazu gehört auch sowas wie Verknüpfungen zwischen Tabellen. Die lösche ich lieber manuell in der Anwendung als über das Cascading mit Foreign Keys. Das hat ganz einfach den Grund, dass ich die Datenbank als Persistenzschicht sehe und diese meiner Meinung nach von der Anwendungslogik kaum was bis gar nichts enthalten sollte.

    Das wäre dann aber der idealistische Ansatz. Und ich habe mittlerweile eingesehen, dass eine Graustufe oft besser ist als Schwarz oder Weiß. Selbst in der Softwareentwicklung.

    Insofern stimme ich Mechanics zu: Sobald die Logik komplexer wird, sollte sie in der Anwendung sein. Oder vielleicht kann man es anders formulieren: Ich würde so viel wie möglich in der Anwendung halten und nur wenn es wirklich einen dicken Vorteil bringt, Dinge in die Datenbank zu verlagern, würde ich sie da hin packen.

    Ich stelle mir in solchen Fällen immer die Frage: Was, wenn ich als Persistenzschicht plötzlich keine Datenbank, sondern eine XML-Datei hätte? Wenn ich mit der rohen XML-Datei arbeiten würde, wäre es von Vorteil, die Abhängigkeiten über die Anwendung zu löschen. Habe ich einen XML-DB-Manager, der referentielle Integrität sicherstellt und Kaskadierung unterstützt, kann es im guten alten dicken Vorteilsfall wiederum sinnvoll sein, das den XML-DB-Manager machen zu lassen.

    TL;DR: Es kommt auf den Fall an.



  • Oh, und da du im Titel Trigger erwähnt hast: Das sehe ich sogar etwas kritischer als Fremdschlüssel. Wir hatten in unserer (recht großen) Anwendung mal Trigger in der Datenbank, aber haben die dann raus genommen, weil sie sich nicht bewährt haben. Man wusste nicht, dass ein Trigger da ist oder es ist Programmlogik dazu gekommen, die den Triger zerstört hat. Wenn du ein Event triggern willst, wenn ein bestimmter Fall eintritt, empfehle ich wärmstens, das im Programmcode zu tun. Du kommst in Teufels Küche, wenn du die Logik zu sehr auf Programmcode und DB verteilst.



  • Matr schrieb:

    Ich stelle mir in solchen Fällen immer die Frage: Was, wenn ich als Persistenzschicht plötzlich keine Datenbank, sondern eine XML-Datei hätte?...

    Sehe ich jetzt nicht unbedingt als das ausschlaggebende Kriterium. Gewisse Anforderungen darf man an die Persistenzschicht schon stellen, und wenn sie etwas mehr erledigen kann, ist es sehr wahrscheinlich kein Nachteil.

    Dein zweites Beispiel ist genau das, was mich bei sowas stört. Das hat man schlecht im Griff. Alles ist irgendwie verteilt und man hat keine zentrale Stelle, wo man sieht, was eigentlich passiert. Irgendwo wird im Code was gemacht, dann gibts aber noch Trigger, die was erledigen, und irgendwelche stored procedures. Und alles ganz sicher nicht dokumentiert und keiner blickt durch. Also "Logik" will ich auf jeden Fall im Code sehen.
    Bei Constraints ist es dann schon die Frage... Referenzielle Integrität sollte die Datenbank auf jeden Fall abdecken. Aber bereits sowas wie min-max Einschränkungen wäre etwas, was ich nicht in der Datenbank hinterlegen würde. Das sind Business Rules, die sich ändern können. Für sowas benutzt man am besten eine Art Rules Engine und versteckt das nicht irgendwo hinter Tabellendefinitionen, wo das wieder keiner findet.



  • Ich bin auch kein Fan von cascading deletes. Einfach weil dadurch zu schnell Mist passieren kann.

    Bin mir aber nicht sicher ob hier cascading deletes gemeint waren, oder die andere Richtung. Also das Löschen des Primärdatensatzes wenn es keine Zeilen mehr in den Detailtabellen gibt die den Primärdatensatz referenzieren. Das ist etwas was ich bisher nur selten gebraucht habe, und wo ich es gebraucht habe, habe ich dafür Garbage-Collection Jobs gemacht. Der Code dazu befindet sich in einer Stored Procedure, und als Scheduler der das periodisch aufruft verwende ich den Job-Scheduler von MS-SQL Server (den "SQL Server Agent").

    Foreign Keys aber auf jeden Fall in der DB vermerken sofern die Performance es zulässt.

    Was Trigger angeht würde ich sagen: kommt drauf an. Journaltabellen befüllen - also was wann wo von wem in einer bestimmten Tabelle geändert wurde - geht z.B. sehr gut mit Triggern. Ebenso hab' ich bei bestehenden Systemen wo verschiedene Programme direkt auf die DB zugreifen schon Trigger für andere Dinge verwendet. Allerdings hauptsächlich für Checks, also Trigger die bestimmte Bedingungen prüfen und dann ggf. ein Rollback machen und den Batch mit nem Fehler abbrechen.


Log in to reply