Guten Nachmittag,
folgende Situation:
Ich hab ein Objekt, das pro Prozess einige Daten enthält. Daneben habe ich ein weiteres Objekt, das als Vorlage für so ein Prozess dient. Beide Objekte haben einige Gemeinsamkeiten, aber auch einige Unterschiede, sodass sich Vererbung anbietet.
Daneben sollen beide Objekte, sowohl der eigentliche Prozess, als auch die Vorlage dazu, eine Liste von zusätzlichen Daten haben, hier brauche ich eine m:n-Beziehung.
Ich hoffe, es wird klar, was ich vor habe 😃
Meine Frage ist nun: Wie setzt man das am besten auf einer relationalen Datenbank um?
Ich arbeite mit EF Core und einer SQL-Server-Datenbank auf.
Mir fallen dazu vier Optionen ein:
Option 1:
Für Prozess und Vorlage eine entsprechende Basis und das wird mit TPT gemappt. Das Problem ist allerdings, dass ich eine m:n-Beziehung für eine weitere Tabelle brauche und in dieser Verbindungs-Tabelle dann nicht klar ist, für welche Ziel-Tabelle der Fremdschlüssel sein soll.
TPH finde ich unpassend (oder unschön), da die Daten-Unterschiede recht umfangreich sein werden, einen konkreten technischen Grund dagegen habe ich aber nicht.
Gibt es eine halbwegs performante Möglichkeit, den Fremdschlüssel anhand einer Discriminator-Spalte in der m:n-Verbindungs-Tabelle auf eine andere Ziel-Tabelle "umzulenken"?
Ich versuche es Mal zu skizzieren, die NVARCHAR(MAX)-Spalten sind stellvertretend für viele weitere Spalten:
Process
BIGINT Id
NVARCHAR(MAX) Data
NVARCHAR(MAX) ProcessDataTemplate
BIGINT Id
NVARCHAR(MAX) Data
NVARCHAR(MAX) TemplateDataListItem
BIGINT M_Id :::
Option 2:
Die Option 1, bloß mit TPH und dann damit leben, dass immer ein Großteil der Tabelle überflüssig ist.
ProcessOrTemplate
BIGINT Id
NVARCHAR(MAX) Data
NVARCHAR(MAX) ProcessData
NVARCHAR(MAX) TemplateData
BIT IsTemplate :::ListItem
BIGINT M_Id :::
Option 3:
Ebenfalls nach TPH-Prinzip, allerdings die Unterschiede in eigene Tabellen auslagern und pro Ableitung eine entsprechend eigene Referenz darauf einbauen. Am Ende in der Datenbank ist die Tabelle dann schön simpel aufgebaut, es ist bloß je nach Ableitung eine der Fremdschlüssel Null.
ProcessOrTemplate
BIGINT Id
NVARCHAR(MAX) Data
BIGINT ProcessDataId :::ProcessData
BIGINT Id
NVARCHAR(MAX) DataTemplateData
BIGINT Id
NVARCHAR(MAX) DataListItem
BIGINT M_Id :::
Option 4:
Sowohl Prozess als auch Vorlage sind weiter als Ableitungen einer Basisklasse und mit TPT gemappt. Daneben gibt es auch für die m:n-Zwischentabelle eine Ableitungs-Hierarchie, die konkreten Ableitungen haben dann eine eigene Referenz zum Prozess bzw. zur Vorlage.
Process
BIGINT Id
NVARCHAR(MAX) Data
NVARCHAR(MAX) ProcessDataTemplate
BIGINT Id
NVARCHAR(MAX) Data
NVARCHAR(MAX) TemplateDataProcessOrTemplateListItem
BIGINT M_Id :::
===============
Ich persönlich mag Option 1, allerdings sieht die im Moment nicht aus, als wäre sie ohne kranke Hacks möglich.
Als Alternative gefällt mir Option 4 am besten, da ich die komplexen Ableitungen in der Datenbank voneinander getrennt habe und die erzwungene TPH-Tabelle denkbar simpel gehalten wird.
Was denkt ihr dazu?
Beste Grüße
NuGet Packages im Code auslesen
lock Alternative für async/await
Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.
Hallo,
Hallo witte und danke für deine Antwort
1.
Das wäre dann ja im Prinzip Option 4, oder wie meinst Du das?
2.
Ich brauch leider die Vererbung, da die teils aufwändige Logik auf die gemeinsamen Daten aufbaut. Der Punkt ist nämlich, dass die Vorlage genauso lange wie ein Prozess behandelt werden soll, bis sich Prozess-Bezogene Daten ändern.
Klar könnte ich dafür auch ein Interface definieren, aber wie gut funktioniert das dann noch mit LINQ to SQL? Das müsste ich Mal austesten.
NuGet Packages im Code auslesen
lock Alternative für async/await
Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.