Laden...

[EF6 Code First, MVC5] Anwendung mit mehreren Datenbanken

Erstellt von MrSparkle vor 9 Jahren Letzter Beitrag vor 9 Jahren 2.723 Views
MrSparkle Themenstarter:in
5.658 Beiträge seit 2006
vor 9 Jahren
[EF6 Code First, MVC5] Anwendung mit mehreren Datenbanken

Hallo allerseits,

ich habe hier eine Anwendung, die einen DbContext verwendet, in der alle Anwendungsdaten gespeichert werden. Darin befinden sich z.B. Personal- und Stammdaten, Daten der Warenhaltung, der Buchhaltung usw.

Jetzt gibt es eine neue Anforderung, daß jeder Geschäftsbereich seine Daten in einer eigenen Datenbank speichern und eine eigene Anwendung bekommen soll. Jede dieser einzelnen Anwendungen soll also eine eigene Datenbank bzw. DbContext bekommen und zusätzlich auf die Datenbank mit den Personal- und Stammdaten zugreifen können, um jeden Geschäftsvorgang einem Mitarbeiter oder einem Standort zuordnen zu können.

Das würde bedeuten, daß jede Anwendung zwei DbContexte hat, die auf unterschiedliche Datenbanken zugreifen. Zwischen den Daten in den zwei DBs existieren aber Fremdschlüssel-Beziehungen, die der EF nicht abbilden kann.

Nach meinen bisherigen Rechercheergebnissen habe ich zwei Möglichkeiten:

  • Jede dieser Beziehung über Datenbank- bzw. Context-Grenzen hinweg manuell mit einer eigenen Abfrage auflösen. Das macht viel Arbeit und schadet der Performance.
  • Anstatt auf zwei Datenbanken gleichzeitig zuzugreifen, in der ersten Datenbank Procedures zum Zugriff auf die Daten der zweiten Datenbank erstellen, und dann im DbContext darauf mappen, so wie hier beschrieben: Code First Insert/Update/Delete Stored Procedures. Das scheint mir aber nicht der Anforderung zu entsprechen, daß die Daten in getrennten DBs liegen sollen, auch wenn sie physisch in einer anderen DB liegen.

Gibt es evtl. noch eine andere Möglichkeit, dieses Problem zu lösen oder zu umgehen?

Danke schonmal,
Christian

Weeks of programming can save you hours of planning

T
415 Beiträge seit 2007
vor 9 Jahren

Das ist aus informationstechnischer Sicht echt eine ziemlich ungünstige Anforderung. Eine weitere Idee könnte ich noch beisteuern. Wie ist das Szenario denn gehalten? Wird auf die Personal- und Stammdaten nur lesend zugegriffen? Das würde meine Idee zumindest vereinfachen. Du könntest in diesem Fall auf Replicationen zurückgreifen. Du hast also eine Master DB, die diese Daten hält und in der sie gepflegt werden. Die anderen Abteilungen, die diese Daten ebenfalls benötigen haben die entsprechenden Tabellen auch in ihren Datenbanken. Und diese konkreten Tabellen werden nun per Replication gegen die Master DB abgeglichen. Ich gebe zu, das ist auch nicht der Königsweg. Aber ich habe auf diese Weise mal ein ähnliches Problem gelöst, um den Datenbestand zwischen zwei Firmenstandorten synchron zu halten.

16.842 Beiträge seit 2008
vor 9 Jahren

Dass gewisse Fremdschlüssel in anderen Systemen verwaltet werden ist ja keine neue Sache.
Das ist zum Beispiel mit ein Grund, wieso bei SAP es quasi keine fixen Relationen in der Datenbank gibt, sondern alles über Logik abgedeckt wird: es kann nicht sichergestellt werden, dass die Informationskette und die Relationen hier eingehalten werden.

Ich sehe keine andere Möglichkeit, die in einer physikalischen Trennung einhergeht, als Deine Variante 1.
Wie gesagt; das ist jetzt auch kein unübliches Verhalten - aber ein (leider) Muss in vielen Angelegenheiten.

PS: auch die Big5 (Facebook, Twitter, Microsoft, Amazon, Google) trennen über die Fremschlüssel in externen Datenbanken zwischen Benutzer- und Businessdaten.
Ist ja auch ein Sicherheitsfaktor.

MrSparkle Themenstarter:in
5.658 Beiträge seit 2006
vor 9 Jahren

Hi t2t,

danke für den Hinweis. Ja, auf die Datenbank mit den Personal- und Stammdaten wird von allen anderen Anwendungen nur lesend zugegriffen.

Replikation führt allerdings wieder dazu, daß die Daten tatsächlich in allen Datenbanken vorhanden sind. Die Anforderung ist aber, daß die Daten in getrennten DBs liegen sollen.

Es geht im Wesentlichen um die Umsetzung einer Datenschutz-Richtlinie, nach der persönliche Daten von Mitarbeitern und Kunden getrennt von den Geschäftsvorgängen gespeichert werden müssen.

Hi Abt,

danke für die Infos. Für die Variante 1 hab ich noch eine konkrete Frage. Die Anwendung besteht im Wesentlichen aus Listen mit Geschäftsvorgängen, die einem oder mehreren Mitarbeitern bzw. Kunden zugeordnet sind. Die Namen der Mitarbeiter und Kunden sollen in den Listen auch angezeigt werden. Bisher reicht eine einzige Datenbankabfrage aus, um die gesamte Liste zu füllen:


var transactions = context.Transactions
  .Include(m => m.Employee)
  .Include(m => m.Employee.Team)
  .Include(m => m.Customer) // etc. ...
  .ToList();

Habe ich jetzt eine Liste mit 100 Einträgen, werden aus einer einzigen Datenbankabfrage mindestens 101 Datenbankabfragen, da ich jeden Listeneintrag mit Daten aus der externen Datenbank abgleichen muß. Gibt es dafür eine Optimierungsmöglichkeit?

Christian

Weeks of programming can save you hours of planning

P
1.090 Beiträge seit 2011
vor 9 Jahren

Hi MrSparkle,

ohne es jetzt ausprobiert zu haben. Es sollte eigendlich Funktionieren pro Datenbank mit einer abfrage auszukommen. In der Abfrage für die Anwendungsdaten bekommst du z.B. ja die IDs der Personaldaten. In der nächsten Abfrage kannst du dir alle Datensätze zurückgeben lassen, die in der "Liste" der IDs sind. Was dann 2. Abfragen währen.

MFG
Björn

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

W
955 Beiträge seit 2010
vor 9 Jahren

Habe ich jetzt eine Liste mit 100 Einträgen, werden aus einer einzigen Datenbankabfrage mindestens 101 Datenbankabfragen, da ich jeden Listeneintrag mit Daten aus der externen Datenbank abgleichen muß. Gibt es dafür eine Optimierungsmöglichkeit? Hallo,
wenn die Anzahl der Mitarbeiter beschränkt ist könnte man sie parallel zu der Kundenanfrage laden (Task.WhenAll), sie in ein Dictionary wandeln und dann zuordnen (vllt auf VM-Ebene).

502 Beiträge seit 2004
vor 9 Jahren
  • Anstatt auf zwei Datenbanken gleichzeitig zuzugreifen, in der ersten Datenbank Procedures zum Zugriff auf die Daten der zweiten Datenbank erstellen, und dann im DbContext darauf mappen, so wie hier beschrieben:
    >
    . Das scheint mir aber nicht der Anforderung zu entsprechen, daß die Daten in getrennten DBs liegen sollen, auch wenn sie physisch in einer anderen DB liegen.

Warum sollte das denn den Anforderungen widersprechen? Ob der Zugriff nun über einen separaten DbContext erfolgt oder über ein und den selben und dann via SPs (oder Views oder was auch immer) auf die andere DB zugegriffen wird ist doch aus Sicht der Datenspeicherung völlig unerheblich. Und im Fall von (ich vermute mal) SQL Server ist es auch aus Sicherheitsaspekten irrelevant, da die zweite DB ihre eigenen Berechtigungen etc. haben kann. Und diese müssen - egal wie der Zugriff letztlich erfolgt - immer "erfüllt" sein, damit der User auch was tun kann.

Ich für meinen Teil habe die selbe Thematik schon vielfach eingesetzt (zumeist mit Views, da bei uns üblicherweise nur Lesezugriffe auf die zweite DB erfolgen müssen) und bin damit problemlos durch unseren internen und externen (=Kunden-) Datenschutz-Audits gekommen. Wichtig ist aus meiner Sicht nur, dass die Sicherheitsrelevanten Bereiche (z.B. Berechtigungen des einzelnen Users) quasi transparent weitergereicht werden, so dass sich durch den neuen Zugriffsweg keine Sicherheitslücken auftun - was gerade in Bezug auf Personaldaten o.ä. im Falle einer Lücke leicht zum Problem ausarten könnte...

Bart Simpson

P.S. Beim SQL-Server ist es durch diese Technik sogar Problemlos möglich nicht nur auf Daten in anderen DBs zuzugreifen, sondern es können sogar andere (physische) Server im Spiel sein (Stichwort: Linked Server).

Praxis ist wenn alles funktioniert und keiner weiss warum.
Theorie ist wenn man alles weiss, aber nichts funktioniert.

Bei uns wird Theorie und Praxis vereint: Nichts funktioniert und keiner weiss warum...

2.760 Beiträge seit 2006
vor 9 Jahren

Ist auch eine Frage was denn mit den Daten im Client hauptsächlich passieren soll und wie viele es sind.

Habe vor kurzem ganz gute Erfahrungen damit gemacht Sqlite in einer Client-Anwendung, die ihre Daten
aus verschiedenen Quellen bezieht zu verwenden.

Die Anwendung besteht im Wesentlichen aus Listen mit Geschäftsvorgängen, die einem oder mehreren Mitarbeitern bzw. Kunden zugeordnet sind. Die Namen der Mitarbeiter und Kunden sollen in den Listen auch angezeigt werden.

Wenn auf die Stammdaten ohnehin nur lesend zugregriffen wird, dann kannst du die DB als schnellen in-memory cache betrachten. Downside: ich habe keinen Weg gefunden die Datenbanken zu transferieren, ohne sie vorher in ein File zu speichern. Das geht mit der Backup-Api: PInvoke-Signaturen für die SQLite Backup-API

Wenn man nicht wie ich in diesem Fall an SQLite gebunden ist, denke ich wird man evtl. passendere DBs finden. Der Ansatz funktioniert aber ziemlich gut.