N-Layer-Datenbankanwendung ohne Verwendung eines ORM. Wie gibt die Benutzeroberfläche an, welche Daten für die Anzeige benötigt werden?
Ich suche hier nach Hinweisen und Informationen. Ich mache dieses CW, da ich vermute, dass es keine einzige richtige Antwort gibt. Dies ist für C #, daher werde ich unten auf Linq verweisen. Ich entschuldige mich auch für den langen Beitrag. Lassen Sie mich die Frage hier zusammenfassen, und dann folgt die vollständige Frage.
Zusammenfassung: In einer 4-Schichten-UI / BLL / DAL / DB-Anwendung kann wie an der Benutzeroberfläche geändert werden, um mehr Spalten (z. B. in einem Raster) anzuzeigen, ein Durchsickern durch die Geschäftslogikschicht und in die Datenzugriffsschicht zu vermeiden Besorgen Sie sich die anzuzeigenden Daten (vorausgesetzt, sie befinden sich bereits in der Datenbank).
Nehmen wir eine mehrschichtige Anwendung mit 3 (4) Schichten an:
BenutzeroberflächeBusiness Logic Layer (BLL)Datenzugriffsschicht (DAL)Datenbank (DB; die 4. Schicht)In diesem Fall ist die DAL dafür verantwortlich, SQL-Anweisungen zu erstellen und für die Datenbank auszuführen, wobei Daten zurückgegeben werden.
Ist die einzige Möglichkeit, eine solche Ebene "korrekt" zu erstellen, um nur immer "select *" zu tun? Für mich ist das ein großes Nein, aber lassen Sie mich erklären, warum ich mich wundere.
Angenommen, ich möchte für meine Benutzeroberfläche alle Mitarbeiter anzeigen, die über eine aktive Beschäftigungsaufzeichnung verfügen. Mit "aktiv" meine ich, dass die Beschäftigungsaufzeichnungen von-bis-Daten heute enthalten (oder vielleicht sogar ein Datum, das ich in der Benutzeroberfläche festlegen kann).
Nehmen wir in diesem Fall an, ich möchte eine E-Mail an alle diese Personen senden, sodass ich in der BLL einen Code habe, der sicherstellt, dass ich noch keine E-Mails an dieselben Personen gesendet habe, usw.
Für die BLL werden nur minimale Datenmengen benötigt. Vielleicht ruft es die Datenzugriffsebene auf, um die Liste der aktiven Mitarbeiter abzurufen, und dann einen Anruf, um eine Liste der E-Mails abzurufen, die es gesendet hat. Dann schließt es sich diesen an und erstellt eine neue Liste. Vielleicht könnte dies mit Hilfe der Datenzugriffsschicht geschehen, dies ist nicht wichtig.
Wichtig ist, dass für die Business-Schicht nicht wirklich viele Daten benötigt werden. Möglicherweise muss nur die eindeutige Kennung für jeden Mitarbeiter angegeben werden, damit beide Listen übereinstimmen, und dann "Dies sind die eindeutigen Kennungen der aktiven Personen, an die Sie noch keine E-Mail gesendet haben". Konstruiere ich dann DAL-Code, der SQL-Anweisungen erstellt, die nur das abrufen, was die Business-Schicht benötigt? Dh nur "ID AUS MITARBEITERN WÄHLEN WO ..."?
Was mache ich dann für die Benutzeroberfläche? Für den Benutzer ist es möglicherweise am besten, abhängig von viel mehr Informationen hinzuzufügenWarum Ich möchte E-Mails versenden. Zum Beispiel möchte ich vielleicht einige rudimentäre Kontaktinformationen oder die Abteilung, für die sie arbeiten, oder den Namen ihres Managers usw. einfügen, um nicht zu sagen, dass ich zumindest die Informationen zu Name und E-Mail-Adresse anzeigen möchte.
Wie erhält die Benutzeroberfläche diese Daten? Ändere ich die DAL, um sicherzustellen, dass ich genügend Daten an die Benutzeroberfläche zurückgebe? Ändere ich die BLL, um sicherzustellen, dass genügend Daten für die Benutzeroberfläche zurückgegeben werden? Wenn die vom DAL an die BLL zurückgegebenen Objekt- oder Datenstrukturen auch an die Benutzeroberfläche gesendet werden können, muss die BLL möglicherweise nicht stark geändert werden, aber die Anforderungen der Benutzeroberfläche wirken sich auf eine Schicht aus, mit der sie nicht kommunizieren sollte . Und wenn die beiden Welten mit unterschiedlichen Datenstrukturen arbeiten, müssten wahrscheinlich Änderungen an beiden vorgenommen werden.
Und was passiert, wenn die Benutzeroberfläche geändert wird, um dem Benutzer durch Hinzufügen weiterer Spalten noch mehr Unterstützung zu bieten? Wie weit muss ich gehen, um die Benutzeroberfläche zu ändern? (Vorausgesetzt, die Daten sind bereits in der Datenbank vorhanden, sodass dort keine Änderungen erforderlich sind.)
Ein Vorschlag, der aufgetaucht ist, ist die Verwendung von Linq-To-SQL und IQueryable, sodass die BLL, wenn die DAL behandelt, was (wie in welchen Datentypen) und warum (wie in WHERE-Klauseln) IQueryables zurückgibt Geben Sie diese möglicherweise an die Benutzeroberfläche zurück, die dann eine Linq-Abfrage erstellen kann, die die benötigten Daten abruft. Der Benutzeroberflächencode könnte dann die erforderlichen Spalten abrufen. Dies würde funktionieren, da mit IQuerables die Benutzeroberfläche die Abfrage letztendlich tatsächlich ausführt und dann mit "select new {X, Y, Z}" angeben kann, was benötigt wird, und bei Bedarf sogar andere Tabellen hinzufügen kann.
Das sieht für mich unordentlich aus. Dass die Benutzeroberfläche den SQL-Code selbst ausführt, obwohl er sich hinter einem Linq-Frontend versteckt hat.
Damit dies geschieht, sollte es der BLL oder der DAL nicht gestattet sein, die Datenbankverbindungen zu schließen, und in einer IoC-Welt könnte der DAL-Dienst etwas früher entsorgt werden, als es der UI-Code wünscht Die Linq-Abfrage endet möglicherweise mit der Ausnahme "Auf ein entsorgtes Objekt kann nicht zugegriffen werden".
Also suche ich nach Hinweisen. Wie weit sind wir entfernt? Wie gehst du damit um? Ich halte die Tatsache, dass Änderungen an der Benutzeroberfläche durch die BLL und in die DAL gelangen, für eine sehr schlechte Lösung, aber im Moment sieht es nicht so aus, als könnten wir es besser machen.
Bitte sag mir, wie dumm wir sind und beweise mir das Gegenteil.
Und beachten Sie, dass dies ein Altsystem ist. Das Ändern des Datenbankschemas ist noch nicht in den letzten Jahren vorgesehen. Daher ist eine Lösung zur Verwendung von ORM-Objekten, die im Wesentlichen "select *" entspricht, keine Option. Wir haben einige große Tabellen, die wir nicht durch die gesamte Liste der Ebenen ziehen möchten.