Laden...

Mehrere Applikationen, die auf die selben Basisentitäten zugreifen

Erstellt von Daniel_3_17 vor 7 Jahren Letzter Beitrag vor 7 Jahren 4.124 Views
D
Daniel_3_17 Themenstarter:in
100 Beiträge seit 2008
vor 7 Jahren
Mehrere Applikationen, die auf die selben Basisentitäten zugreifen

Hi,

wir haben vier Applikationen, die alle gewisse gemeinsame Daten haben. Eine Applikation war bisher die Führende und die anderen haben darauf zugegriffen und / oder benötigte Daten synchronisiert und entsprechend redundant in der eigenen Datenbank abgelegt.

Die Synchronisierung soll jetzt möglichst wegfallen und wir haben uns bisher überlegt, die gemeinsam genutzten Daten in ein Kern-Projekt abzukapseln, damit alle Applikationen darauf zugreifen können.

Die Probleme, die jetzt schon in der Planung entstanden:

Einige der Entitäten des neuen Kerns müssen in den Applikationen erweitert werden.
So hat ein Verein (auf den generell aus allen Applikationen zugegriffen werden soll), in einigen Anwendungen noch weitere Eigenschaften wie z. B. ob es Mitglied einer bestimmten Organisation ist.

Wie würdet ihr dazu die Datenstruktur und die Projekte aufbauen?

Ein weiteres Problem ist es, wenn in Projekt A ein Verein angelegt wird. Dieser soll ja dann im Kern-Projekt abgelegt werden. Wie bekommen das dann die anderen Anwendungen (bzw. deren Datenbankstruktur) sinnvoll mit? Und ist das so überhaupt sinnvoll?

Lösungsansatz 1)
Alle applikationsrelevanten Vereinsdaten (obige Mitgliedschaft) werden mit im Kern abgelegt. Z. B. über extra Tabellen: "Vereine_AnwendungA_Erweiterungen".

Lösungsansatz 2)
Applikationsrelevante Daten zum Verein werden in der Applikationsdatenbank gespeichert. Sobald ein Objekt im Kern erstellt wird, werden alle Anwenwendungen angetriggert, sodass diese über die Neuigkeit informiert werden und die benötigten Erweiterungs-Objekte erstellen können.

Beispiel Lösungsansatz 2:

Verein (im Kern)

Id
Bezeichnung

App1Verein (in App1)

Id
KernVereinId
HatFunktionA
List<Sportarten>

App2Verein (in App2)

Id
KernVereinId
DarfAntraegeErstellen
List<Antraege>

Bei den Synchronisierungen haben wir halt immer sorge, dass etwas schief gehen kann. Auch müsste eine Art Transaktion drum herum konstruiert werden.

Die Kommunikation zum Kern soll über OData passieren. Wenn eine Anwendung spezielle Daten aus anderen Anwendungen haben will, soll dies auch über OData stattfinden.

Da wir nicht die ersten sind, die dieses Problem haben, werdet ihr sicher mit der perfekten Lösung um die Ecke kommen. Danke schon mal dafür. 😄

Beste Grüße!
Daniel, Daniel, Thomas

2.078 Beiträge seit 2012
vor 7 Jahren

werdet ihr sicher mit der perfekten Lösung um die Ecke kommen

Bloß gibt es keine perfekte Lösung 😛

Spricht denn irgendwas dagegen, alles in eine Datenbank zu legen?
Wenn die Unterschiede nicht zu gravierend sind, würde ich das tun. So habt ihr nur eine Datenbank für alle Anwendungen und könnt auf lange Sicht weitere Features aus einer Anwendung in den Kern ablegen, sodass die andere Anwendung sie auch nutzen kann.
Ich denke dabei an Office, wie man ganz hervorragend Excel-Dokumente oder Visio-Diagramme in PoerPoint bearbeiten kann. Das wird denke ich durch getrennte Datenbanken nur erschwert.

Wenn das eher unwahrscheinlich ist oder aus irgendeinem anderen Grund eine gemeinsame Datenbank eher die letze Wahl sein soll, dann würde ich den Vorschlag 2 verwenden, allerdings nicht mit einem zweiten Schlüssel, der auf den Kern zeigt, sondern direkt den Primär-Schlüssel dafür verwenden.

Im Prinzip hast Du also schon die Lösungswege geboten, andere sehe ich hier auch nicht.

Was das Triggern von neuen Datensätzen angeht:

Ihr könntet die Datenbank hinter einem Datenzugriffs-Service verstecken. Wenn irgendeine der Anwendungen gestartet wird, prüft sie, ob der Service bereits läuft und startet ihn gegebenenfalls.
Nachteil ist, dass das denke ich nicht ganz so trivial ist, denn dann müsst ihr immer bei einem anderen Prozess bzw. Service nach den Daten fragen und könnt nicht einfach die DLL einbinden und nutzen.

Als Alternative: Ein ehemaliger Kollege hat mal erzählt, dass der SQL-Server über Trigger andere .NET-Anwendungen benachrichtigen kann. Das wäre natürlich die einfachste Lösung.
Ich weiß allerdings nicht, wie das geht, aber vielleicht finde ich ja noch was ^^

Als dritte Möglichkeit:
Ihr nehmt im Kern eine zusätzliche möglichst schlanke Tabelle auf, in der Flags mit Datum gelagert werden. Da könnte dann z.B. ein Flag namens "NewCoreClubCreated" und einem Datum von vor 10 Minuten drin stehen.
Alle anderen Anwendungen fragen regelmäßig dort nach, ob es was neues gibt, vergleichen das Datum mit dem Stand in der eigenen Datenbank und wissen so, welchen Stand sie haben.

PS:

Schau mal hier: CLR-Trigger

Ich hab's jetzt nur grob überflogen, aber es scheint genau das zu sein, was ich meine.
Du kannst im SQL-Server eine Methode registrieren, damit diese dann vom SQL-Server als Trigger aufgerufen wird.

Und hier: Gewusst wie: Erstellen und Ausführen eines CLR SQL Server-Triggers

D
Daniel_3_17 Themenstarter:in
100 Beiträge seit 2008
vor 7 Jahren

Hi Palladin007,

Danke für deine Hilfe. Auch sehr interessant, was es für Möglichkeiten gibt aus der MSSQL-Datenbank zu triggern. Wir verwenden bei dem Projekt jedoch eine MySQL-Datenbank.

Alles in eine Datenbank abzulegen wurde bei uns im Team diskutiert, nach einer "Abstimmung" jedoch abgelehnt.

Der Plan ist jetzt so, dass wir in der Kern-Datenbank die gemeinsam genutzten Tabellen ablegen. Zusätzlich gibt es dann für jede Anwendung die Möglichkeit, zusätzliche Daten für die Entitäten in die Kern-Datenbank abzulegen. Dies jedoch in einer separaten Tabelle, quasi als Key-Value-Store. Das ganze wird auf C#-Seite dann abstrahiert, sodass man als Entwickler der Anwendung auf typisierte Objekte zugreifen kann.

Ich bin gespannt ob der Plan auf geht. 🤔

Grüße!

2.078 Beiträge seit 2012
vor 7 Jahren

Also ich bin ja kein Fan von dem Key-Value-Plan 😄
Das ist sinnvoll, wenn die Inhalte wirklich dynamisch sind, wie z.B. Produkt-Informationen, die der Benutzer selber bestimmen kann.
Ob man das in eurem Fall so machen sollte, weiß ich nicht, war noch nie in der Situation, ich würde es aber lassen.

Existieren die Anwendungen denn immer nebeneinander?
Wenn die Anwendungen nicht gerade unabhängig voneinander sein müssen, bietet es sich vielleicht an, alle Daten in einer Datenbank zu halten mit der vollständigen Tabellen-Definition? Das dürfte auch die Kommunikation untereinander vereinfachen, alles hat ja den gleichen Kern und wenn z.B. eine Anwendung nicht genutzt wird, gibts eben leere Tabellen, das fällt nicht wirklich auf.
Die Unterschiede können dann mittels Vererbung gelöst werden, EF6 macht das ganz gut.

Ich persönlich bleibe aber ein Fan von getrennten Datenbanken. DIe Unterschiede werden dann über Vererbung abgebildet. Das Ganze hinter einem Repository versteckt ist auch nicht so schwer umzusetzen.
Der Kern hat dann die grundlegenden Daten in der eigenen Datenbank und das passende Interface dazu sowie die Implementierung.
In einer der Anwendung gibt es dann eine zweite Detail-Tabelle. Der ForeignKey ist in beiden Tabellen der PrimaryKey. Das Interface dazu leitet von dem aus dem Kern ab, die Implementierung erbt von der aus dem Kern.
Wenn ihr einen OR-Mapper nutzt, dann kann die Detail-Implementierung auch eine Fassade um die OR-Mapper-Klasse sein.
Eventuell geht es auch ohne Repository, aber z.B. bei EF weiß ich nicht, wie sich das verhält, wenn die Entity-Klasse eine unbekannte Entity-Klasse als Basis hat.

Auf diese Weise sind die Daten technisch getrennt, die Abhängigkeiten sind aber klar erkennbar.
Beim Entwickeln merkt man das aber nicht, da gibt es nur die Vererbung, mit der man arbeiten muss und die macht denke ich mehr einfach als kompliziert ^^

T
314 Beiträge seit 2013
vor 7 Jahren

Wieso nicht einfach als Table_App_Extensions welche die Erweiterungen der Applikation für eine bestimmte Tabelle enthält? (bzw. Table_Extensions wenns in ner eigenen Datenbank ist) Dort einfach per Key referenzieren und fertig?

Ein KeyValue stelle ich mir relativ schwierig vor, wenn ein Datensatz mehrere zusätzliche Werte enthält.

2.078 Beiträge seit 2012
vor 7 Jahren

So ungefähr meinte ich das

Wenn der PrimaryKey der Core-Tabelle auch der PrimaryKey der Detail-Tabelle ist, lässt sich das ziemlich leicht realisieren, auch wenn kein OR-Mapper verwendet wird, der das unterstützt.

Die Vererbung macht den Zugriff auf die Datenbank dann schön einfach.

Mit einer Key-Value-Tabelle würde es zwar auch gehen und denke ich auch nicht so schwer zumindest nicht schwerer, allerdings müssen so Dinge wie Fremdschlüssel-Beziehungen nach gebaut werden, Einschränkungen, Datentyp, Trigger, etc.
Ein großer Teil des Aufwandes besteht dann darin, Features vom verwendeten Datenbank-System nachzubauen und alleine dieser Satz tut schon fast weh 😄
Kompliziert könnte es aber werden, wenn auf einmal eine Fremdschlüsselbeziehung zu einer normalen Tabelle aufgebaut werden soll - das geht nämlich nicht 😄 Zumindest nicht mit den Mitteln des Datenbank-Systems - außer vielleicht mit MsSQL dank den tollen Triggern.

Ich denke, ihr baut euch da eine Zeitbombe.
Anfangs sieht das vielleicht einfacher aus, später könnte das aber genauso ein schwer zu wartender Bestandteil werden, den ihr dann in ein paar Jahren versucht, raus zu bekommen.

D
Daniel_3_17 Themenstarter:in
100 Beiträge seit 2008
vor 7 Jahren

Bei einer App-Erweiterungstabelle "Table_App_Extensions" in der Kern-Datenbank sehen wir das Problem, dass sich das Datenmodell der Kern-Datenbank bei einer Änderung auch für alle anderen Applikationen ändert und diese entsprechend auch aktualisiert werden müssten. (Wegen der Entity Framework Migrationen)

16.806 Beiträge seit 2008
vor 7 Jahren

Ich seh das wie Palladin: ihr baut euch da von Anfang ein ein Konstrukt auf, dessen Explosion absehbar ist.
Niemand baut heute mehr so einen (garantiert) schlecht zu wartenden, unübersichtlichen Monolithen, wenn er nicht muss.

Eigentlich steht ihr auch nur vor einem völlig normalen Alltagsproblem: Versionierung von Schnittstellen und Ressourcen.
Nur würde ich an eurer Stelle so vorgehen, dass dies möglichst leichtgewichtig ist und nicht wie - so scheint es mir - ihr mit einer Keule alles erschlagen wollt.

Ob ihr zudem glücklich werdet, dass alle vier Applikationen direkt auf die Datenbank zugreifen; das mag ich zu bezweifeln.
Eine entsprechend versionierte API wäre deutlich einfacher in der Handhabung sowie der Kommunikation.

T
314 Beiträge seit 2013
vor 7 Jahren

Das wäre der Applikation doch völlig egal, wieso sollte diese aktualisiert werden müssen?

Sofern ihr diese Gefahr seht, wieso wollt ihr überhaupt diese Daten die zu unterschiedlichen Applikationen gehören in einer Datenbank zusammenwerfen? Sollte eure Kernkomponente sich auch nicht nur um den Kern kümmern und nicht Teile diverser Applikationen abbilden?

2.078 Beiträge seit 2012
vor 7 Jahren

Ich rate einfach mal, dass die Anwendungen einen gemeinsamen Daten-Stamm haben, wie z.B. Personen-Daten. Eine der Anwendungen ist dann dafür da, diesen Datenstamm zu bearbeiten, während die Anderen nur damit arbeiten.

In so einem Fall ist es schon sinnvoll, das alles zentral abzulegen.

T
314 Beiträge seit 2013
vor 7 Jahren

Hmmm ...

Einige der Entitäten des neuen Kerns müssen in den Applikationen erweitert werden.
So hat ein Verein (auf den generell aus allen Applikationen zugegriffen werden soll), in einigen Anwendungen noch weitere Eigenschaften wie z. B. ob es Mitglied einer bestimmten Organisation ist.

Klingt für mich nicht danach. Ich habe es so verstanden, dass alle Applikationen auf die Basisdaten eines Vereins zugreifen. Manche dieser Applikation benötigen weitere Vereinsinformationen (Zuordnung zu Organisation).

Sofern mehrere Applikationen diese Erweiterungen benötigen, muss man natürlich aufpassen, dass die Daten nicht über diverse Datenbanken verteilt werden (oder sich dessen zumindstens bewusst sein). In diesem Fall würde ich dies wohl auch in der "Kerndatenbank" aufnehmen.

Aber soetwas kann/ist ja auch immer eine Fall zu Fall Unterscheidung. Die Zuordnung eines Vereins kann ja durchaus in der Kerndatenbank stehen (genauso wie die Verwaltung der Organisationen). In dem Fall würde ich es auch nicht als Zusatz zu einer bestimmten Applikation sehen, sondern als Teil des Kerns. Es ist ja auch niemals notwendig, dass jede Applikation das komplette Model versteht/nutzt.

Im Gegensatz dazu würde ich solche erweiternde Eigenschaften die gefühlt doch sehr anwendungsspezifisch sind wie z.B. DarfAntraegeErstellen nicht im Kern sehen.

T
2.219 Beiträge seit 2008
vor 7 Jahren

Ein Konzept, dass ich empfehlen würde, wäre die Daten im Kern in einer DB zu speichern.
Die Apps sollten dann per Webservice arbeiten.

Dann hast du eine DB.
Der Webservice bietet dann entsprechende Methoden samt Authentifizierung an um die Daten aus der DB zu laden und zu speichern.
Deine Apps können dann die Daten entsprechend abfragen/anlegen.

Somit habt ihr den Webservice als Zentralle Schnittstelle.
Die Daten können dann auch in einer DB gespeichert werden.

@t0ms3n
Auch wenn die Anwendungsspezifischen Daten nicht in den Kern gehören, hast du dann das Problem der Datenhaltung.
Wilslt du solche Daten dann in einer eigene DB abspeichern oder willst du sogar ganze Datenstämme redundant halten?
Auch wenn es von der Achitektur suboptimal ist, würde ich auch spezifische Daten im Kern lagern.
Wenn die Daten von X Anwendungen auf die selbe Basis zugreifen müssen, muss man dann entweder die Trennung von spezifschen Daten in der DB vornehmen, also die zusätzlichen Teile in gesonderten Tabellen speichern oder eben redundante Daten halten.

Erstes wäre noch sinnvoll letztes aber unsinn und eben redundanz.

Nachtrag:

Eine Aufteilung auf DB Ebene könnte dann so aussehen.

Tabellen:

Verein
ID,
Bezeichnung,
DarfAntragStellen

SportArten
ID,
Bezeichnung,
...

VereinsSportArten
VereinsID,
SportArtenID

VereinsAnträge,
VereinsID,
AntragsID,

Anträge
ID,
Bezeichnung,
...

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

T
314 Beiträge seit 2013
vor 7 Jahren

Wenn die Daten von X Anwendungen auf die selbe Basis zugreifen müssen, muss man dann entweder die Trennung von spezifschen Daten in der DB vornehmen, also die zusätzlichen Teile in gesonderten Tabellen speichern oder eben redundante Daten halten.
Erstes wäre noch sinnvoll letztes aber unsinn und eben redundanz.

Ich erwähnte ja bereits Eingangs die Möglichkeit dies über entsprechende zusätzliche Tabellen im Kern abzulegen, aber auf jeden Fall eine Key/Value Tabelle vermeiden würde.

Aber ja, abhängig davon von wem und wie die zusätzlichen Informationen genutzt werden, würde ich diese nicht zwangsläufig in der Kerndatenbank halten wollen. Ob man diese nun replizieren möchte oder nur die Ids entsprechend vorhält oder dies über Views abbildet sei mal dahin gestellt.

(Ich schieße hier ja nicht aus, dass es hier sinnvoll ist alle Daten in der Kerndatenbank zu haben.)

2.078 Beiträge seit 2012
vor 7 Jahren

Ich denke, wir sind uns alle einige: Key-Value-Pair BLOSS NICHT!! 😄

Ob es sinnvoll ist die Daten zentral in der Core-Datenbank zu halten oder aufgeteilt auf spezifische Datenbanken, das kann nur der Daniel bzw. sein Team sagen.

Meine Meinung:
Ist der Umfang der zusätzlichen Daten überschaubar oder gehören die Daten rein logisch zu den Core-Daten (z.B. allgemeine Vereinsdaten und konkrete Vereinsdaten), dann sollten diese Daten in den Kern.
Sind die Daten spezifischer und wirklich nur für eine Anwendung sinnvoll, dann würde ich sie auslagern.

Wichtig ist beim Aufteilen dann nur, dass die Datenbank-Ebene gut versteckt ist, vorzugsweise nach dem Repository-Pattern. Die Detail-Daten-Interfaces erben von den Core-Daten-Interfaces.
Muss am Ende dann doch mal etwas aus einer Detail-Datenbank in den Kern übertragen werden, dann muss so die Anwendung nicht bearbeitet werden. Ein einfaches Verschieben einer Property aus einem Interface in ein Basis-Interface sollte keine Probleme verursachen, nur das Abrufen der Daten läuft dann anders.

Die Daten aufzuteilen sollte man sicher nicht auf die leichte Schulter nehmen, am Ende kommen wieder mehrere Datenbanken raus. Klug umgesetzt ist aber keine Synchronisation notwendig und der Kern hat nicht so viel - aus Sicht der anderen Anwendungen - Müll dabei.

Aber wie gesagt:
Was von beidem sinnvoll ist, können wir nur raten, das müssen die unter sich klären.

16.806 Beiträge seit 2008
vor 7 Jahren

(...) am Ende kommen wieder mehrere Datenbanken raus.

Korrekt. Das entspricht übrigens der strukturellen Basis von Microservices.