2

Ich habe Eric Evans 'Domain Driven Design Buch gelesen und ich habe versucht, einige der Konzepte anzuwenden.DDD: Modellierung der eindeutigen globalen/lokalen ID von Aggregaten in PostgreSQL

In seinem Buch spricht Eric über Aggregate und wie Aggregatwurzeln eine eindeutige globale ID haben sollten, während Aggregatmitglieder eine eindeutige lokale ID haben sollten. Ich habe versucht, dieses Konzept auf meine Datenbanktabellen anzuwenden, und ich stoße auf einige Probleme.

Ich habe zwei Tabellen in meiner PostgreSQL-Datenbank: Einrichtungen und Mitarbeiter, wo Mitarbeiter einer einzigen Einrichtung zugeordnet werden können.


In der Vergangenheit würde ich die Mitarbeiter Tisch legen sich wie folgt dar:

CREATE TABLE "employees" (
    "employeeid" serial NOT NULL PRIMARY KEY, 
    "facilityid" integer NOT NULL, 
    ... 
    FOREIGN KEY ("facilityid") REFERENCES "facilities" ("facilityid") 
); 

wo Employeeid eine weltweit eindeutige ID ist. Ich würde dann im Backend Code für die Validierung der Zugriffskontrolle hinzufügen, um zu verhindern, dass Benutzer einer Einrichtung auf Zeilen zugreifen, die zu anderen Einrichtungen gehören. Ich habe das Gefühl, dass dies nicht der sicherste Weg ist.



Was ich jetzt überlege ist dieses Layout:

CREATE TABLE "employees" (
    "employeeid" integer NOT NULL, 
    "facilityid" integer NOT NULL, 
    ... 
    PRIMARY KEY ("employeeid", "facilityid"), 
    FOREIGN KEY ("facilityid") REFERENCES "facilities" ("facilityid") 
); 

wo Employeeid einzigartig ist (lokal) für eine gegebene FacilityID muss aber mit einem FacilityID gepaart werden global eindeutig zu sein.

Konkret ist es das, was ich suche:

Mitarbeiter A (Employeeid: 1, FacilityID: 1)
Mitarbeiter B (Employeeid: 2, FacilityID: 1)
Mitarbeiter C (Employeeid: 1, FacilityID: 2)

wobei A, B und C sind 3 verschiedene Mitarbeiter und ...
Hinzufügen eines Mitarbeiters D zum Objekt 1 würde ihm die Schlüssel (Employeeid: 3, FacilityID: 1)
Hinzufügen eines Mitarbeiters E nach Einrichtung 2 würde ihm die Schlüssel geben (Mitarbeiter-ID: 2, Einrichtungs-ID: 2)


Ich sehe zwei Möglichkeiten, dies zu erreichen:

  1. I Trigger oder gespeicherte Prozeduren verwenden können, um automatisch neue employeeids zu erzeugen und zu speichern, die letzten IDs für jede Anlage in einer anderen Tabelle für einen schnelleren Zugriff, aber ich bin besorgt über Concurrency-Probleme und am Ende mit 2 Mitarbeitern aus der gleichen Einrichtung mit der gleichen ID.

  2. Ich könnte möglicherweise eine neue Sequenz für jede Einrichtung erstellen, um die employeeIDs zu verwalten, aber ich befürchte, am Ende Tausende von Sequenzen zu verwalten und mit Verfahren zum Löschen dieser Sequenzen, falls eine Einrichtung gelöscht wird. Ist da etwas nicht in Ordnung? Es scheint mir schwer zu sein.

Welchen Ansatz sollte ich wählen? Gibt es etwas, was ich verpasse?

+1

Ich bin ein wenig verwirrt über das, was Sie erreichen möchten (und was das mit DDD zu tun hat). Sie beschreiben zuerst eine Eins-zu-Viele-Beziehung als Voraussetzung, zeigen dann aber Daten für eine Viele-zu-Viele-Beziehung in dem "Dies ist, wonach ich suche:". Werden Sie die Employee-Entität außerhalb dieses beschränkten Kontexts bloßstellen? Nach meiner Erfahrung besteht der Unterschied zwischen globalen und lokalen IDs darin, dass Sie einfach global eine UUID (oder GUID) erstellen. Dann weißt du, dass diese ID in begrenzten Kontexten einzigartig sein wird. –

+0

Ich habe meine Frage bearbeitet, um sie hoffentlich weniger zweideutig zu machen. Die Beziehung, die ich möchte, ist One-to-Many und die Entität Employee wird nicht außerhalb des beschränkten Kontexts verfügbar gemacht. Ich suche hauptsächlich nach dem besten Weg, diese Mitarbeiteridentitäten zu generieren. – akp

Antwort

1

Ich folge aus Ihrer Frage, dass Sie eine einzige Datenbank für alle Einrichtungen ausführen, oder zumindest, wenn Sie eine lokale Datenbank als "Master" für jede Einrichtung haben, die die Daten in einem kombiniert werden müssen zentrale Datenbank ohne Kollisionen.

Ich würde die facilitid die hoher Ordnung Teil des Primärschlüssels machen. Sie könnten wahrscheinlich neue Mitarbeiterzahlen mit einem einfachen SELECT max(employeeid) + 1 ... WHERE facilityid = n-Ansatz zuweisen, da das Hinzufügen von Mitarbeitern zu einer einzelnen Einrichtung vermutlich nicht hundertmal pro Sekunde aus mehreren gleichzeitigen Quellen geschieht. Es besteht die Möglichkeit, dass dies zu gelegentlichen Serialisierungsfehlern führen kann, aber meiner Meinung nach sollte jeder Datenbankzugriff über ein Framework erfolgen, das diese erkennt und die Transaktion automatisch erneut versucht.

1

Ich denke, Sie haben hier das aggregierte Stammkonzept überstrapaziert. In meinem Verständnis der Modellierung eines Mitarbeiters (das hängt von Ihrem Kontext ab) ist ein Mitarbeiter fast immer ein aggregierter Root, möglicherweise referenziert durch eine andere aggregierte Root-Funktion.

Sowohl Mitarbeiter als auch Einrichtung haben fast immer natürliche Schlüssel. Für den Mitarbeiter ist dies in der Regel eine Mitarbeiter-ID (gedruckt auf Mitarbeiteridentifikationsausweisen, oder zumindest in der Personal-Software-System verwaltet) und Einrichtungen haben diese natürlichen Schlüssel zu fast immer mit einem Ort Teil und eine Nummer wie "MUC-1 "für die einrichtung 1 in münchen. Aber das hängt alles von deinem Kontext ab. Falls Mitarbeiter und Einrichtung diese natürlichen Schlüssel haben, sollte Ihr Datenbankmodell ziemlich klar sein.

Verwandte Themen