Ich arbeite in einem Unternehmen, das nur gespeicherte Prozeduren für den gesamten Datenzugriff verwendet, was es sehr ärgerlich macht, unsere lokalen Datenbanken bei jedem Commit, den wir ausführen müssen, synchron zu halten. Ich habe in der Vergangenheit einige grundlegende ORMs verwendet und finde die Erfahrung viel besser und sauberer. Ich möchte dem Entwicklungsleiter und dem Rest des Teams vorschlagen, ein ORM für die zukünftige Entwicklung zu verwenden (der Rest des Teams ist nur mit gespeicherten Prozeduren vertraut und hat noch nie etwas anderes verwendet). Die aktuelle Architektur ist .NET 3.5, geschrieben wie .NET 1.1, mit "God-Klassen", die eine seltsame Implementierung von ActiveRecord verwenden und untypisierte DataSets zurückgeben, die in Code-Behind-Dateien durchlaufen werden. Die Klassen funktionieren ungefähr so:
class Foo {
public bool LoadFoo() {
bool blnResult = false;
if (this.FooID == 0) {
throw new Exception("FooID must be set before calling this method.");
}
DataSet ds = // ... call to Sproc
if (ds.Tables[0].Rows.Count > 0) {
foo.FooName = ds.Tables[0].Rows[0]["FooName"].ToString();
// other properties set
blnResult = true;
}
return blnResult;
}
}
// Consumer
Foo foo = new Foo();
foo.FooID = 1234;
foo.LoadFoo();
// do stuff with foo...
Es gibt so gut wie keine Anwendung von Entwurfsmustern. Es gibt überhaupt keine Tests (niemand weiß, wie man Unit-Tests schreibt, und das Testen erfolgt durch manuelles Laden der Website und Herumstöbern). Durchsuchen Sie unsere Datenbank mit 199 Tabellen, 13 Ansichten, 926 gespeicherten Prozeduren und 93 Funktionen. Ungefähr 30 Tabellen werden für Batch-Jobs oder externe Dinge verwendet, der Rest wird in unserer Kernanwendung verwendet.
Lohnt es sich überhaupt, in diesem Szenario einen anderen Ansatz zu verfolgen? Ich spreche davon, nur voranzukommen, weil wir den vorhandenen Code nicht umgestalten dürfen, da "es funktioniert", sodass wir die vorhandenen Klassen nicht zur Verwendung eines ORM ändern können, aber ich weiß nicht, wie oft wir stattdessen brandneue Module hinzufügen Ich bin mir nicht sicher, ob ein ORM der richtige Ansatz ist (zu viel in gespeicherte Prozeduren und DataSets investiert). Wenn es die richtige Wahl ist, wie soll ich den Fall für die Verwendung einer darstellen? Der einzige Vorteil, den ich mir vorstellen kann, ist, saubereren Code zu haben (auch wenn dies möglicherweise nicht der Fall ist, da die aktuelle Architektur nicht der Fall ist). Ohne Rücksicht auf ORMs würden wir ORMs grundsätzlich auf zukünftige Module ausrichten, aber die alten würden immer noch die DataSets verwenden), und es wäre weniger mühsam, sich daran zu erinnern, welche Prozedurskripte ausgeführt wurden und welche ausgeführt werden müssen. usw. aber das wars auch schon und ich weiß nicht, wie überzeugend ein argument wäre. Die Wartbarkeit ist ein weiteres Problem, das außer mir niemand zu befürchten scheint.
quelle
Antworten:
Gespeicherte Prozeduren sind schlecht, oft langsam und ungefähr so effizient wie gewöhnlicher clientseitiger Code.
[Die Beschleunigung ist normalerweise auf die Art und Weise zurückzuführen, wie die Client- und die Schnittstelle für gespeicherte Prozeduren entworfen wurden und wie Transaktionen als kurze, fokussierte SQL-Bursts geschrieben werden.]
Gespeicherte Prozeduren sind einer der schlechtesten Orte, an denen Code abgelegt werden kann. Es unterteilt Ihre Anwendung in zwei Sprachen und Plattformen nach häufig zufälligen Regeln.
[Diese Frage wird mit -30 bewertet, da viele, viele Leute der Meinung sind, dass gespeicherte Prozeduren magische Kräfte haben und trotz der von ihnen verursachten Probleme verwendet werden müssen.]
Das Verschieben des gesamten Codes für gespeicherte Prozeduren auf den Client erleichtert die Arbeit für alle erheblich.
Sie müssen das Schema und das ORM-Modell von Zeit zu Zeit aktualisieren. Schemaänderungen sind jedoch von ORM-Änderungen isoliert, was eine gewisse Unabhängigkeit zwischen Anwendungen und Datenbankschema ermöglicht.
Sie können alle gespeicherten Prozeduren testen, reparieren, warten, verstehen und anpassen, während Sie sie umschreiben. Ihre App wird ungefähr gleich ausgeführt und weniger anfällig, da Sie nicht mehr in zwei verschiedene Technologien einbrechen.
ORMs sind keine Zauberei, und gute Fähigkeiten im Datenbankdesign sind absolut notwendig, damit sie funktionieren.
Programme mit viel Client-SQL können außerdem langsam werden, weil sie die Transaktionsgrenzen nicht genau kennen. Einer der Gründe, warum gespeicherte Prozeduren schnell zu sein scheinen, besteht darin, dass gespeicherte Prozeduren ein sehr sorgfältiges Design von Transaktionen erzwingen.
ORMs erzwingen nicht auf magische Weise ein sorgfältiges Transaktionsdesign. Das Transaktionsdesign muss noch genauso sorgfältig durchgeführt werden wie beim Schreiben gespeicherter Prozeduren.
quelle
Gespeicherte Prozeduren sind gut, schnell und sehr effizient und der ideale Ort, um Ihren datenbezogenen Code abzulegen. Das Verschieben des gesamten Codes auf den Client vereinfacht die Arbeit für Sie als Cliententwickler geringfügig (geringfügig, da Sie das Schema und das ORM-Modell nach dem Festschreiben von Änderungen noch aktualisieren müssen), aber Sie verlieren den gesamten vorhandenen Code und nehmen Änderungen vor Ihre App ist langsamer und wahrscheinlich fragiler, wenn man bedenkt, dass all diese SQL-Kenntnisse verloren gehen.
Ich frage mich, ob die Datenbankadministratoren dort sitzen und sagen: "Oh, bei jedem Commit muss ich den Client erneut herunterfahren, wir sollten den gesamten Code stattdessen in DB-Formulare verschieben."
In Ihrem Fall sollten Sie in der Lage sein, das vorhandene benutzerdefinierte ORM (dh Ihre lustigen Klassen) ohne Verluste durch das eines anderen zu ersetzen, mit Ausnahme von Änderungen an der Art und Weise, wie Ihr Code-Behind-Code geschrieben wird. Sie können die SPs auch behalten, da die meisten (alle?) ORMs sie gerne anrufen. Daher würde ich empfehlen, diese "Foo" -Klassen durch ein ORM zu ersetzen und von dort aus fortzufahren. Ich würde nicht empfehlen, Ihre SPs zu ersetzen.
PS. Es scheint, dass Sie in den Code-Behind-Klassen viele gemeinsame Codes haben, die sie zu einem eigenständigen Entwurfsmuster machen. Was denkst du, ist ein Designmuster an erster Stelle! (ok, es ist vielleicht nicht das beste oder sogar ein gutes, aber es ist immer noch ein DP)
Bearbeiten: und jetzt mit Dapper , ist jeder Grund, Sprocs über ein schweres ORM zu vermeiden, weg.
quelle
ds.Tables[0].Rows[0]["FooName"].ToString()
Mist los . Manager liebt gespeicherte Prozeduren? Er darf sie behalten. Es wäre jedoch physikalisch unmöglich zu behaupten, dass es eine schlechte Sache war, all den sich wiederholenden Code von Boilerplate in etwas zu verschieben, das beispielsweise von LINQ to SQL generiert wurde.Sie scheinen zu versuchen, Ihr Team von einem Extrem (gespeicherte Prozeduren und Datensätze) zu einem anderen (einem vollständigen ORM) zu führen. Ich denke, es gibt andere, inkrementellere Änderungen, die Sie an der Implementierung vornehmen können, um die Codequalität Ihrer Datenzugriffsebene zu verbessern, die Ihr Team möglicherweise eher akzeptiert.
Der halbfertige Implementierungscode für aktive Datensätze, den Sie veröffentlicht haben, ist nicht besonders elegant. Ich würde empfehlen, das Repository-Muster zu untersuchen, das einfach zu verstehen und zu implementieren ist und bei .NET-Entwicklern sehr beliebt ist. Dieses Muster wird oft mit ORMs assoziiert, aber es ist genauso einfach, Repositorys mit ADO.NET zu erstellen.
Wie für DataSets - igitt! Mit Ihren Klassenbibliotheken lässt sich viel einfacher arbeiten, wenn Sie statisch (oder sogar dynamisch) typisierte Objekte zurückgeben. Ich glaube, diese Abbildung erklärt meine Meinung zu DataSet besser als ich könnte.
Sie können die gespeicherten Prozesse auch löschen, ohne zu einem ORM zu springen - es ist nichts Falsches an der Verwendung von parametrisiertem SQL. In der Tat würde ich es definitiv der Verwendung von gespeicherten Prozessen vorziehen, es sei denn, Sie haben komplexe Prozeduren, die mehrere Roundtrips zum Server ersparen. Ich hasse es auch, wenn ich eine alte Datenbank öffne und eine endlose Liste von CRUD-Prozeduren sehe.
Ich rate nicht von der Verwendung von ORMs ab - ich benutze sie im Allgemeinen für die meisten Projekte, an denen ich arbeite. Ich kann jedoch nachvollziehen, warum der Versuch, eines in dieses Projekt und Ihr Team einzuführen, möglicherweise zu viel Reibung führt. Das klingt so, als hätten sie vor etwa acht Jahren aufgehört, neue Dinge zu lernen. Trotzdem würde ich auf jeden Fall einen Blick auf die neue Generation von "Micro ORMs" werfen, wie Dapper (der diese Site nicht weniger antreibt ) und Massive , die beide unglaublich einfach zu bedienen sind und Sie näher am SQL halten als a Ein typisches ORM, und das Ihr Team möglicherweise eher akzeptiert.
quelle
Ich bin in einer ähnlichen Situation, unsere Hardware, Macht und Politik lehnen sich an die Seite der Datenbank, also durchläuft alles eine gespeicherte Prozedur. Leider sind sie für einen Codierer eine Qual, insbesondere wenn es um die Generierung von Metadaten und Code geht, da gespeicherte Prozeduren nicht so umfangreiche Metadaten enthalten wie Tabellen.
Unabhängig davon können Sie mit gespeicherten Prozessen immer noch eleganten und sauberen Code schreiben. Ich implementiere derzeit das Repository-Muster selbst mit allen gespeicherten Prozeduren. Ich würde vorschlagen, FluentAdo.net nach seiner brillanten Idee zu durchsuchen, wenn Sie Daten von einem Datenleser zurück auf Ihre Geschäftsobjekte übertragen. Ich habe einen Teil dieser Idee übernommen und für meine eigene Lösung verwendet.
quelle
JFTR - Ich bin ein niedriger PHP-Entwickler, aber das klingt nach einer überwiegend politischen Angelegenheit.
In Anbetracht des Ausmaßes der "Fäulnis", die die App stützt, würde es - abgesehen von den Best Practices - einen erheblichen Aufwand geben, sie zu beseitigen. Das hört sich so an, als würde es an das Neuschreiben von Territorien angrenzen.
Können Sie garantieren, dass die von Ihnen vorgeschlagene Alternative Vorteile bringt, um die Kosten für das Unternehmen zu rechtfertigen? Ich vermute, dass es schwierig sein könnte, den ROI dieses Unternehmens an das Unternehmen zu verkaufen. Es sei denn, die App ist instabil oder Sie können den finanziellen Erfolg der Überarbeitung nachweisen - dies könnte sich als schwierig erweisen.
Ist ORM die einzige Alternative zu SPROCS? Es gibt ein paar Designmuster zwischen einem vollständigen ORM und Vanilla SQL. Vielleicht können Sie den Prozess starten, indem Sie diese SPROCS nach und nach aus der DB in eine DBAL bringen. Es besteht natürlich die Gefahr, dass dies mit der Zeit zu einem Homebrew-ORM wird - aber Sie wären dem Ziel einen Schritt näher gekommen.
quelle
Wir sind vor ein paar Jahren von SP zu ORM gewechselt.
In einem Fall mussten wir 80 Tabellen aktualisieren. Das alte Schätzmodell hätte hierfür mit entlib und SP 80 Stunden veranschlagt. Wir haben es in 10 gemacht :)
Dadurch konnten wir den Zeitaufwand für die Entwicklung der Datenzugriffsschicht um 80% reduzieren.
quelle
Mir kommt eher vor, dass das zugrunde liegende Problem darin besteht, dass Ihre Bereitstellungen nicht ordnungsgemäß und automatisch funktionieren.
Es ist möglicherweise einfacher, eine Continuous Build-Engine einzurichten, die weiß, wie die Datenbanken nach jedem Commit nach Bedarf bearbeitet werden.
quelle