Objektorientiertes Paradigma ist der Standard für Anwendungssoftware. Relationales DBMS - ein Standard zum Speichern von Daten in Anwendungssoftware. Ja, Sie können in Haskell schreiben und Daten ausschließlich in ClickHouse speichern. Aber es geht um den Mainstream.
Mit ORM können Sie
eine Eule auf einen Globus ziehen, um so zu tun, als gäbe es kein RDBMS, und die Daten werden in einem Objektmodell gespeichert, das für OOP besser geeignet ist. Es bleibt ein "kleines" solches Problem - diese Abstraktion "fließt" wie viele andere. Wo im Objektmodell eine Verknüpfung zu einem anderen Objekt im Datenbank-Fremdschlüssel und der ID besteht. Zum Zeitpunkt der Materialisierung des Unternehmens stehen wir vor der Wahl:
- Laden Sie alles herunter und verlieren Sie Speicherplatz
- Geben Sie explizit an, welche Abhängigkeiten wir herunterladen möchten und welche nicht, und verstoßen Sie gegen das Tell-Don't-Ask- Prinzip
- Laden Sie Abhängigkeiten implizit nach Bedarf mit Lazy Load und erhalten Sie Leistungsprobleme irgendwo im aufgerufenen Code
Welche Art von Bein sollten Sie abschneiden: links oder rechts?
TLDR Lazy Load ist nicht so schlecht, wenn es nur zum Schreiben und nicht zum Lesen verwendet wird. Aber alles ist nicht so einfach und es gibt viele Nuancen.Im Laufe der Zeit kam ich zu dem Schluss, dass Lazy Load und / oder die Abhängigkeit von Entitäten von der Implementierung von ORM unter bestimmten Bedingungen das geringere Übel ist.
Lesen Sie im gelesenen Subsystem immer nur DTO
In 90% der Fälle treten Probleme mit Lazy Load genau beim Lesen auf. Wir erhalten die Liste der Entitäten, gehen sie durch und beginnen mit der Schleife und beginnen mit der Auswahl aller erforderlichen Daten. Wir erhalten eine Reihe von Anfragen an die Datenbank. In diesem Fall müssen in den meisten Fällen nur die Daten abgerufen, serialisiert und in Form von JSON zurückgesendet werden. Warum dann überhaupt Entitäten laden? Es ist nicht erforderlich, diese Daten zum Änderungs-Tracker-UOW hinzuzufügen, um die gesamte Entität zusammen mit den "zusätzlichen" Feldern zu lesen. Stattdessen können Sie immer entweder
Select
oder
ProjectTo
schreiben. Lazy Load ist nicht erforderlich, da der C # -Code von
Select
in SQL übersetzt und auf der Datenbankseite ausgeführt wird.
Was ist, wenn meine Logik nicht in SQL übersetzt wird?
Ich empfehle, die
Kundenbewertung auszuschalten. Erstens können Sie
direkt in sub "helfen" und Unterstützung für die erforderlichen Funktionen hinzufügen. Keine schlechte Option, wenn es um einfaches Computing geht, nicht um Geschäftsregeln. Option Nummer zwei: Extrahieren Sie die Schnittstelle aus der Entität und implementieren Sie sie sowohl in der Entität als auch im DTO.
In der Datenbank gibt es beispielsweise zwei Felder: "Preis ohne Rabatt" und "Preis mit Rabatt". Wenn das Feld "Rabattpreis" ausgefüllt ist, verwenden Sie es, wenn nicht, verwenden Sie das Feld mit dem üblichen Preis. Fügen Sie eine weitere Regel hinzu. Beim Kauf von 3 Produkten zahlen Sie nur für die 2 teuersten, wobei auch regelmäßige Rabatte berücksichtigt werden.
Die Implementierung kann wie folgt sein:
public interface IHasProductPrice { decimal BasePrice { get; } decimal? SalePrice { get; } } public class Product: IHasProductPrice {
Im Schreibsubsystem ist Lazy Load nicht so beängstigend
Im Schreibsubsystem hingegen reicht oftmals nur die ID zum Schreiben nicht aus. Bei allen Arten von Überprüfungen lesen Sie häufig die gesamte Entität, da das Objektparadigma das Kombinieren von Daten und Operationen innerhalb des Klassenobjekts und seiner Invariante umfasst. Wenn das Projekt DDD verwendet, müssen Schreib- / Änderungsvorgänge über den Aggregationsstamm ausgeführt werden und daher nur über ein Objekt und seine Abhängigkeiten. Eine große Anzahl von Abfragen kann nur auftreten, wenn mit verwandten Sammlungen gearbeitet wird.
Zugehörige Sammlungen in Aggregaten
Wenn sich zu viele Daten in der Maschine befinden, kann dies auf ein Konstruktionsproblem hinweisen. Typische Wurzeln der Aggregation - Korb, Bestellung, Paket. Normalerweise arbeiten die Benutzer nicht mit Daten aus Tausenden von Zeilen. Daher ist das Herunterladen der gesamten verknüpften Sammlung möglicherweise nicht die produktivste, aber keine tödliche Operation. Wenn sich jedoch Tausende von Objekten in der Sammlung befinden, ist es möglich, dass es wirklich keine solche Aggregationswurzel gibt, und die Entwickler haben sich diese ausgedacht, da dies mit improvisierten Werkzeugen sehr einfach war.
Was ist, wenn insgesamt noch Tausende von Datensätzen vorhanden sind?
DbContext
den
DbContext
an den
Konstruktor und lesen Sie daraus nur die Daten, die im Kontext der Operation erforderlich sind. Ja, DIP verletzen. Entweder das, oder verwenden Sie das Gerät in diesem Fall überhaupt nicht.
Massenoperationen
Das Importieren einer Datei mit 10.000 Zeilen ist ein großartiges Ziel für Lazy Load. Hier werden zu allen Problemen des Lesesubsystems auch die Bremsen von ChangeTracker hinzugefügt. Für die Massenaufzeichnung müssen Sie separate
Tools verwenden . Ich bevorzuge Batch-Erweiterungen, da Sie auch hier auf das Erstellen von Entitäten verzichten können. Für besonders schwere Fälle gibt es gute alte gespeicherte Prozeduren und sogar
spezielle DBMS-Tools .
Life Hack
Wenn Sie sowohl eine Massenoperation als auch eine konventionelle implementieren müssen, müssen Sie mit einer Massenoperation beginnen. Ein normaler Betrieb ist nur ein Sonderfall von Massencode in einer Sequenz mit nur einem Element.